Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File ownership after docker cp

How can I control which user owns the files I copy in and out of a container?

The docker cp command says this about file ownership:

The cp command behaves like the Unix cp -a command in that directories are copied recursively with permissions preserved if possible. Ownership is set to the user and primary group at the destination. For example, files copied to a container are created with UID:GID of the root user. Files copied to the local machine are created with the UID:GID of the user which invoked the docker cp command. However, if you specify the -a option, docker cp sets the ownership to the user and primary group at the source.

It says that files copied to a container are created as the root user, but that's not what I see. I create two files owned by user id 1005 and 1006. Those owners are translated into the container's user namespace. The -a option seems to make no difference when I copy the file into a container.

$ sudo chown 1005:1005 test.txt
$ ls -l test.txt
-rw-r--r-- 1 1005 1005 29 Oct  6 12:43 test.txt
$ docker volume create sandbox1
sandbox1
$ docker run --name run1 -vsandbox1:/data alpine echo OK
OK
$ docker cp test.txt run1:/data/test1005.txt
$ docker cp -a test.txt run1:/data/test1005a.txt
$ sudo chown 1006:1006 test.txt
$ docker cp test.txt run1:/data/test1006.txt
$ docker cp -a test.txt run1:/data/test1006a.txt
$ docker run --rm -vsandbox1:/data alpine ls -l /data
total 16
-rw-r--r--    1 1005     1005            29 Oct  6 19:43 test1005.txt
-rw-r--r--    1 1005     1005            29 Oct  6 19:43 test1005a.txt
-rw-r--r--    1 1006     1006            29 Oct  6 19:43 test1006.txt
-rw-r--r--    1 1006     1006            29 Oct  6 19:43 test1006a.txt

When I copy files out of the container, they are always owned by me. Again, the -a option seems to do nothing.

$ docker run --rm -vsandbox1:/data alpine cp /data/test1006.txt /data/test1007.txt
$ docker run --rm -vsandbox1:/data alpine chown 1007:1007 /data/test1007.txt
$ docker cp run1:/data/test1006.txt .
$ docker cp run1:/data/test1007.txt .
$ docker cp -a run1:/data/test1006.txt test1006a.txt
$ docker cp -a run1:/data/test1007.txt test1007a.txt
$ ls -l test*.txt
-rw-r--r-- 1 don  don  29 Oct  6 12:43 test1006a.txt
-rw-r--r-- 1 don  don  29 Oct  6 12:43 test1006.txt
-rw-r--r-- 1 don  don  29 Oct  6 12:47 test1007a.txt
-rw-r--r-- 1 don  don  29 Oct  6 12:47 test1007.txt
-rw-r--r-- 1 1006 1006 29 Oct  6 12:43 test.txt
$ 
like image 802
Don Kirkby Avatar asked Oct 06 '17 20:10

Don Kirkby


People also ask

Does docker copy overwrite?

It seems that docker build won't overwrite a file it has previously copied. I have a dockerfile with several copy instructions, and files touched in earlier COPY directives don't get overwritten by later ones. After building this, $BASE/config/thatfile. yml contains the contents of file1.

How do I change the owner of a docker container?

Similarly, when we change the owner of files using chown, the command consults the /etc/passwd to obtain the uid of a given username. Interestingly, because the username is redundant from the perspective of file ownership, we can change the owner of files to uid that doesn't own by any users in the /etc/passwd file.

How do I copy a file from docker container to local machine?

To summarize, follow these steps to copy a file from a Docker container to a host machine: Obtain the name or id of the Docker container. Issue the docker cp command and reference the container name or id. The first parameter of the docker copy command is the path to the file inside the container.

Is docker a recursive copy?

Docker provides two commands for copying files from the host to the Docker image when building it: COPY and ADD . The instructions are similar in nature, but differ in their functionality: COPY — copies local files recursively, given explicit source and destination files or directories.


3 Answers

You can also change the ownership by logging in as root user into the container :

docker exec -it --user root <container-id> /bin/bash
chown -R <username>:<groupname> <folder/file>
like image 101
ramu Avatar answered Oct 14 '22 11:10

ramu


In addition to @Don Kirkby's answer, let me provide a similar example in bash/shell script for the case that you want to copy something into a container while applying different ownership and permissions than those of the original file.

Let's create a new container from a small image that will keep running by itself:

docker run -d --name nginx nginx:alpine

Now wel'll create a new file which is owned by the current user and has default permissions:

touch foo.bar
ls -ahl foo.bar
>> -rw-rw-r-- 1 my-user my-group 0 Sep 21 16:45 foo.bar

Copying this file into the container will set ownership and group to the UID of my user and preserve the permissions:

docker cp foo.bar nginx:/foo.bar
docker exec nginx sh -c 'ls -ahl /foo.bar'
>> -rw-rw-r--    1 4098     4098           0 Sep 21 14:45 /foo.bar

Using a little tar work-around, however, I can change the ownership and permissions that are applied inside of the container.

tar -cf - foo.bar --mode u=+r,g=-rwx,o=-rwx --owner root --group root | docker cp - nginx:/
docker exec nginx sh -c 'ls -ahl /foo.bar'
>> -r--------    1 root     root           0 Sep 21 14:45 /foo.bar

tar options explained:

  • c creates a new archive instead of unpacking one.
  • f - will write to stdout instead of a file.
  • foo.bar is the input file to be packed.
  • --mode specifies the permissions for the target. Similar to chown, they can be given in symbolic notation or as an octal number.
  • --owner sets the new owner of the file.
  • --group sets the new group of the file.

docker cp - reads the file that is to be copied into the container from stdin.

This approach is useful when a file needs to be copied into a created container before it starts, such that docker exec is not an option (which can only operate on running containers).

like image 44
Dirk Avatar answered Oct 14 '22 12:10

Dirk


Just a one-liner (similar to @ramu's answer), using root to make the call:

docker exec -u 0 -it <container-id> chown node:node /home/node/myfile
like image 5
Aidin Avatar answered Oct 14 '22 11:10

Aidin