moby icon indicating copy to clipboard operation
moby copied to clipboard

`docker cp -a` doesn't preserve ownership information

Open macdjord opened this issue 3 years ago • 7 comments

Description

According to the documentation, docker cp -a is supposed to copy files into or out of a container while preserving file & directory ownership information. It doesn't.

Steps to reproduce the issue:

  • Container 'foobar-dev' has user 'scanner' with UID 1000
  • Host machine has user 'scanner' with UID 1002 & user 'ec2-user' with UID 1000

Describe the results you received:

[foo@bar ~]$ sudo rm -rf save/mounted_keys/
[foo@bar ~]$ docker exec 'foobar-dev' ls -l '/etc/ssh/mounted_keys/'
total 24
-rw-------    1 scanner  scanner        411 Jul 15 02:49 id_ed25519
-rw-r--r--    1 scanner  scanner         99 Jul 15 02:49 id_ed25519.pub
-rw-------    1 root     root           411 Aug  4 22:36 id_ed25519_login
-rw-r--r--    1 root     root            99 Aug  4 22:36 id_ed25519_login.pub
-rw-------    1 root     root          2602 Nov 13  2019 ssh_host_rsa_key
-rw-r--r--    1 root     root           571 Nov 13  2019 ssh_host_rsa_key.pub
[foo@bar ~]$ docker cp --archive 'foobar-dev:/etc/ssh/mounted_keys/'                             './save/'
[foo@bar ~]$ ls -la save/mounted_keys/
total 24
drwxr-xr-x 2 foo  foo   150 Aug  4 18:53 .
drwxrwxr-x 8 foo  foo   152 Nov 28 22:10 ..
-rw------- 1 foo  foo   411 Jul 14 21:49 id_ed25519
-rw------- 1 foo  foo   411 Aug  4 17:36 id_ed25519_login
-rw-r--r-- 1 foo  foo    99 Aug  4 17:36 id_ed25519_login.pub
-rw-r--r-- 1 foo  foo    99 Jul 14 21:49 id_ed25519.pub
-rw------- 1 foo  foo  2602 Nov 13  2019 ssh_host_rsa_key
-rw-r--r-- 1 foo  foo   571 Nov 13  2019 ssh_host_rsa_key.pub
[foo@bar ~]$ sudo chown scanner:scanner save/mounted_keys/id_ed25519
[foo@bar ~]$ sudo chown 1000:1000 save/mounted_keys/id_ed25519.pub
[foo@bar ~]$ ls -la save/mounted_keys/
total 24
drwxr-xr-x 2 foo      foo       150 Aug  4 18:53 .
drwxrwxr-x 8 foo      foo       152 Nov 28 22:10 ..
-rw------- 1 scanner  scanner   411 Jul 14 21:49 id_ed25519
-rw------- 1 foo      foo       411 Aug  4 17:36 id_ed25519_login
-rw-r--r-- 1 foo      foo        99 Aug  4 17:36 id_ed25519_login.pub
-rw-r--r-- 1 ec2-user ec2-user   99 Jul 14 21:49 id_ed25519.pub
-rw------- 1 foo      foo      2602 Nov 13  2019 ssh_host_rsa_key
-rw-r--r-- 1 foo      foo       571 Nov 13  2019 ssh_host_rsa_key.pub
[foo@bar ~]$ sudo rm -rf save/mounted_keys/
[foo@bar ~]$ sudo docker cp --archive 'foobar-dev:/etc/ssh/mounted_keys/'                             './save/'
[foo@bar ~]$ ls -la save/mounted_keys/
total 24
drwxr-xr-x 2 root root  150 Aug  4 18:53 .
drwxrwxr-x 8 foo  foo   152 Nov 28 22:13 ..
-rw------- 1 root root  411 Jul 14 21:49 id_ed25519
-rw------- 1 root root  411 Aug  4 17:36 id_ed25519_login
-rw-r--r-- 1 root root   99 Aug  4 17:36 id_ed25519_login.pub
-rw-r--r-- 1 root root   99 Jul 14 21:49 id_ed25519.pub
-rw------- 1 root root 2602 Nov 13  2019 ssh_host_rsa_key
-rw-r--r-- 1 root root  571 Nov 13  2019 ssh_host_rsa_key.pub

Describe the results you expected:

  • Files id_ed25519 and id_ed25519.pub are created on the host owned by either user 'scanner' or user 'ec2-user', not owned by root.
  • If files cannot be created with the correct ownership (e.g. because the calling user doesn't have permission to perform the necessary chown) then a warning message will be emitted rather than failing silently

Output of docker version:

Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
 Built:             Mon Jul  1 18:51:44 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       e68fc7a/18.06.1-ce
  Built:            Mon Jul  1 18:53:20 2019
  OS/Arch:          linux/amd64
  Experimental:     false

Output of docker info:

Containers: 13
 Running: 12
 Paused: 0
 Stopped: 1
Images: 301
Server Version: 18.06.1-ce
Storage Driver: overlay2
 Backing Filesystem: xfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:
 seccomp
  Profile: default
Kernel Version: 4.14.88-88.76.amzn2.x86_64
Operating System: Amazon Linux 2
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 985.7MiB
Name: ssaas-dev-bastion-02
ID: DIIR:CQL2:BPRH:6SHK:EABX:UTTN:SGB7:SZ6B:PRDP:PMSU:PXWO:DHEQ
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

macdjord avatar Nov 29 '20 03:11 macdjord

Hi @macdjord, I will like to help on this issue. But can you state your reproducing steps clearer? For example, docker cp --archive 'foobar-dev:/etc/ssh/mounted_keys/' seems weird because it has no destination path.

jimlinntu avatar Jan 10 '21 14:01 jimlinntu

From my testing, it seems that copying a file from container to the local machine will not preserve the ownership, but the opposite will (not shown below).

$ docker run -it —rm ubuntu:20.04 bash
root@3a7012ccb7a9:/# adduser haha
root@3a7012ccb7a9:/# touch test
root@3a7012ccb7a9:/# chown haha:haha test
root@3a7012ccb7a9:/# ls -al test
-rw-r--r-- 1 haha haha 0 Jan 10 14:41 test


$ docker cp 3a7012ccb7a9:/test ./
$ ls -al test
-rw-r--r-- 1 user user 0  一  10 22:41 test

jimlinntu avatar Jan 10 '21 14:01 jimlinntu

Hi @macdjord, I will like to help on this issue. But can you state your reproducing steps clearer? For example, docker cp --archive 'foobar-dev:/etc/ssh/mounted_keys/' seems weird because it has no destination path.

You didn't copy the whole line:

[foo@bar ~]$ docker cp --archive 'foobar-dev:/etc/ssh/mounted_keys/'                             './save/'

macdjord avatar Jan 12 '21 01:01 macdjord

From my testing, it seems that copying a file from container to the local machine will not preserve the ownership, but the opposite will (not shown below).

Well, that's a problem. -a is supposed to "copy all uid/gid information", not just in one direction.

macdjord avatar Jan 12 '21 01:01 macdjord

Also ran into this today. If you're going to not implement this, at the very minimum modify the docs.

As a workaround, you can use the tar stream output to fully preserve attributes, e.g.:

# docker cp container:src - | tar xf /dev/stdin -C dest

clarfonthey avatar Aug 16 '21 03:08 clarfonthey

Same issue for me. Would expect files copied from container to preserve uid/gid, but they are all created under root instead.

kazagz avatar Sep 06 '21 12:09 kazagz

any updates on this?

bijeebuss avatar Dec 13 '22 18:12 bijeebuss

I ran into this problem too and looked at the source code. It seems to me the UID/GID are being overwritten here?

https://github.com/moby/moby/blob/b1c112d35e4f1921ca82c9f76d86e5c92c2a9280/pkg/archive/archive.go#L619-L623

When the --archive option is used, containerExtractToDir sets the tar options: https://github.com/moby/moby/blob/3e4c9d90cf6a796334519f0de12ff09608d7abbe/daemon/archive_unix.go#L142-L150

tarCopyOptions always sets ChownOpts in UNIX: https://github.com/moby/moby/blob/3e4c9d90cf6a796334519f0de12ff09608d7abbe/daemon/archive_tarcopyoptions_unix.go#L21-L26

I think this was working in 2016 with 8a7ff5ff746a77e0be601c11540562341b2228c1, but possibly broken in 2017 with 8a34c67a7ec. https://github.com/moby/moby/pull/34590 has more context why this commit was introduced.

@thaJeztah I think you might have brought up a concern in https://github.com/moby/moby/issues/32816#issuecomment-298457178 related to this, but I'm still confused how all this is supposed to work. 😄

stanhu avatar Sep 21 '23 17:09 stanhu