why doesn't chown work in Dockerfile?

115,910

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).

Share:
115,910

Related videos on Youtube

Nandan
Author by

Nandan

SOreadytohelp

Updated on April 22, 2022

Comments

  • Nandan
    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.

  • CashIsClay
    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
    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
    Michael Härtl over 9 years
    Answering myself: The explanation here made sense to me container-solutions.com/2014/12/understanding-volumes-docker
  • kev
    kev about 9 years
    If I mount volume to container, perm switch back to root:root. I use CMD chown -R user:user /path/to/dir && gosu user command to solve this problem.
  • GrayedFox
    GrayedFox over 8 years
    An important point from that article above: "[When VOLUME is specified after a RUN 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
    MauricioOtta about 8 years
    Thanks for answering your own question and saving some of my hair
  • Kamafeather
    Kamafeather over 4 years
    Updated URL for explanation linked by @MichaelHärtl is: blog.container-solutions.com/understanding-volumes-docker
  • jouell
    jouell over 4 years
    Tremendous! A double answer!
  • fccoelho
    fccoelho over 4 years
    I don't declare any VOLUME on my dockerfile and still have this issue... :-(
  • Nihal Sharma
    Nihal Sharma about 4 years
    @fccoelho - found any solution?
  • tripleee
    tripleee about 2 years
    Manually modifying the UID with usermod file is an ugly hack. You can specify the UID at creation with useradd -u 1001