why doesn't chown work in Dockerfile?
Solution 1
Answering my own question: it's declared to be a volume. If you take out the VOLUME instruction, the chown takes effect.
What's more, if you declare the volume after running chown, the chown settings remain in effect.
Solution 2
This blog http://container42.com/2014/11/03/docker-indepth-volumes/ explains this behaviour in detail.
Each instruction in the Dockerfile creates a new container. The instruction make some changes to this container and becomes a new layer. The changes made to "/var/local/testrunner/logs" before VOLUME instruction were made to the actual container filesystem. However, after VOLUME instruction, the directory "/var/local/testrunner/logs" is the mounted directory. The changes made to this directory after VOLUME instruction will apply on the mounted directory and not the actual container filesystem.
Solution 3
For anyone experiencing this issue without volumes, I found a convoluted work around.
Problem:
With a simple Dockerfile as follows:
FROM ubuntu:16.04
RUN useradd -m -d /home/new_user new_user
COPY test_file.txt /home/new_user
RUN chown -R new_user:new_user /home/new_user
CMD ls -RFlag /home
After running:
echo "A file to test permissions." > test_file.txt
docker build -t chown-test -f Dockerfile .
docker run --rm -it chown-test
The output was:
/home:
total 12
drwxr-xr-x 1 root 4096 Jun 15 21:37 ./
drwxr-xr-x 1 root 4096 Jun 15 21:39 ../
drwxr-xr-x 1 root 4096 Jun 15 21:39 new_user/
/home/new_user:
total 24
drwxr-xr-x 1 root 4096 Jun 15 21:39 ./
drwxr-xr-x 1 root 4096 Jun 15 21:37 ../
-rw-r--r-- 1 root 220 Aug 31 2015 .bash_logout
-rw-r--r-- 1 root 3771 Aug 31 2015 .bashrc
-rw-r--r-- 1 root 655 Jul 12 2019 .profile
-rw-r--r-- 1 root 28 Jun 11 19:48 test_file.txt
As you can see the file ownership (e.g. test_file.txt) is still associated with user root
.
Solution:
I found that if I used a numeric UID in the chown
command, I could change the ownership, but only if the UID was not 1000. So I added 1 to the UID of new_user
and then changed the ownership.
FROM ubuntu:16.04
RUN useradd -m -d /home/new_user new_user
# change the uid of new_user to ensure it has whatever it was assigned plus 1 (e.g. if UID was 1000, now it'll be 1001)
RUN id -u new_user | awk '{print $1+1}' | xargs -I{} usermod -u {} new_user
COPY test_file.txt /home/new_user
RUN id -u new_user | xargs -I{} chown -R {}:{} /home/new_user
CMD ls -RFlag /home
After running:
echo "A file to test permissions." > test_file.txt
docker build -t chown-test -f Dockerfile .
docker run --rm -it chown-test
The output was:
/home:
total 12
drwxr-xr-x 1 root 4096 Jun 15 21:37 ./
drwxr-xr-x 1 root 4096 Jun 15 21:37 ../
drwxr-xr-x 1 1001 4096 Jun 15 21:37 new_user/
/home/new_user:
total 24
drwxr-xr-x 1 1001 4096 Jun 15 21:37 ./
drwxr-xr-x 1 root 4096 Jun 15 21:37 ../
-rw-r--r-- 1 1001 220 Aug 31 2015 .bash_logout
-rw-r--r-- 1 1001 3771 Aug 31 2015 .bashrc
-rw-r--r-- 1 1001 655 Jul 12 2019 .profile
-rw-r--r-- 1 1001 28 Jun 11 19:48 test_file.txt
I'm not sure why I was having this issue in the first place. However, since it appears others have had this issue, I thought I'd post my workaround. My use case was creating a docker container that served a jupyter notebook. I created a non-root user to serve the notebook.
Solution 4
In my experience, chown
does not work when mounting to root (VOLUME /test
). Use a non-root location (VOLUME /var/test
).
Related videos on Youtube
Comments
-
Nandan about 2 years
My Dockerfile creates a directory, chown's it, and then lists the directory afterwards. The directory is still owned by root. Why is that?
Here is the Dockerfile:
FROM ubuntu:precise RUN useradd -d /home/testuser -m -s /bin/bash testuser RUN mkdir -p /var/local/testrunner/logs VOLUME ["/var/local/testrunner/logs"] RUN grep testuser /etc/passwd RUN grep root /etc/passwd RUN chown -R testuser:testuser /var/local/testrunner/logs RUN ls -ld /var/local/testrunner/logs
Here is the output from "docker build":
Sending build context to Docker daemon 10.24 kB Sending build context to Docker daemon Step 0 : FROM ubuntu:precise ---> ab8e2728644c Step 1 : RUN useradd -d /home/testuser -m -s /bin/bash testuser ---> Using cache ---> 640f12671c86 Step 2 : RUN mkdir -p /var/local/testrunner/logs ---> Using cache ---> bf7756fd5b1f Step 3 : VOLUME ["/var/local/testrunner/logs"] ---> Using cache ---> 65c73ee76c20 Step 4 : RUN grep testuser /etc/passwd ---> Using cache ---> db72fff0b965 Step 5 : RUN grep root /etc/passwd ---> Running in ebff78df7a9a root:x:0:0:root:/root:/bin/bash ---> ead0ff704a59 Removing intermediate container ebff78df7a9a Step 6 : RUN chown -R testuser:testuser /var/local/testrunner/logs ---> Running in c925f67b2ab4 ---> 253132be935e Removing intermediate container c925f67b2ab4 Step 7 : RUN ls -ld /var/local/testrunner/logs ---> Running in 978bc66aa47e drwxr-xr-x 2 root staff 4096 Oct 1 15:15 /var/local/testrunner/logs
Docker version 1.2.0, build fa7b24f
The host runs Ubuntu 12.04, but with a 3.13.0-36-generic kernel.
-
That Brazilian Guy almost 6 yearsFor issues with onership after COPY, see: stackoverflow.com/questions/44766665/…
-
-
CashIsClay over 9 years"If you declare the volume after running chown, the chown settings remain in effect" This just answered something that's had me stumped for two days. Thank you!
-
Michael Härtl over 9 years@user100464 I wonder if there is a reasonable explanation for this quite odd behavior. It seems you only figured this out by trial & error. Or is this documented somewhere?
-
Michael Härtl over 9 yearsAnswering myself: The explanation here made sense to me container-solutions.com/2014/12/understanding-volumes-docker
-
kev about 9 yearsIf I mount volume to container, perm switch back to
root:root
. I useCMD chown -R user:user /path/to/dir && gosu user command
to solve this problem. -
GrayedFox over 8 yearsAn important point from that article above: "[When
VOLUME
is specified after aRUN
command that modifies the volume], docker is clever enough to copy any files that exist in the image under the volume mount into the volume and set the ownership correctly. This won’t happen if you specify a host directory for the volume (so that host files aren’t accidentally overwritten)." -
MauricioOtta about 8 yearsThanks for answering your own question and saving some of my hair
-
Kamafeather over 4 yearsUpdated URL for explanation linked by @MichaelHärtl is: blog.container-solutions.com/understanding-volumes-docker
-
jouell over 4 yearsTremendous! A double answer!
-
fccoelho over 4 yearsI don't declare any VOLUME on my dockerfile and still have this issue... :-(
-
Nihal Sharma about 4 years@fccoelho - found any solution?
-
tripleee about 2 yearsManually modifying the UID with
usermod
file is an ugly hack. You can specify the UID at creation withuseradd -u 1001