Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Volumes files have root owner when running docker with non-root user. #3124

Closed
Krijger opened this issue Dec 8, 2013 · 42 comments
Closed

Volumes files have root owner when running docker with non-root user. #3124

Krijger opened this issue Dec 8, 2013 · 42 comments

Comments

@Krijger
Copy link

@Krijger Krijger commented Dec 8, 2013

As a non-programmer with a user that is in the docker usergroup
I want to be able to access files created by docker in a volume A that I specified using docker run -v A:B without taking further steps
So that I will not get unexpected behavior


Context
In my use-case, I am creating a docker image to help a non-programmer collaborating on a web development project. I want to supply the image as executable that serves the web app, without the non-programmer having to install lots of stuff. The volume is the directory containing the web project - on the host, so I don't want root:root files to appear there.

I may also create a container with git and some scripts doing the only stuff that the collaborator should have to do.

Using docker in this way is new for me, but I think it is a great use case!


This issue is related to #2372. However, I think this use-case is much more specific and might have higher priority.

@SvenDowideit
Copy link
Contributor

@SvenDowideit SvenDowideit commented Dec 11, 2013

mmm, me too - there is an issue somewhere discussing somethign related.

@Krijger
Copy link
Author

@Krijger Krijger commented Dec 11, 2013

If you can find the issue, please link it (I couldn't).

@SvenDowideit
Copy link
Contributor

@SvenDowideit SvenDowideit commented Dec 11, 2013

yup - sorry, had too long a list of things to track.

generically, #2975 and #2360

darn, I can't find it atm either - I'll continue looking later.

@jessfraz
Copy link
Contributor

@jessfraz jessfraz commented Feb 25, 2015

ping @cpuguy83

@cpuguy83
Copy link
Collaborator

@cpuguy83 cpuguy83 commented Feb 25, 2015

Volumes will now inherit permissions of the files in the image, unless they are bind mounted, for example(docker run -v /path/on/host:/path/in/container), and that is expected behavior.

Based on the linked issues, I believe this issue is resolved, so I am closing.
If not, pleas ping here. Thanks!

@jwgmeligmeyling
Copy link

@jwgmeligmeyling jwgmeligmeyling commented May 23, 2015

I currently experience that files created by the container in a mounted volume are owned by root on the host. I want this to be the same user:group as the user:group that owns the directory. Is this possible?

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented May 23, 2015

@jwgmeligmeyling files and folders created in the volume will have the same uid:gid (numeric) as the user creating them in the container. If you add a user inside the container having the same uid:gid as outside the container and run your contsiner as that user, that should be possible

@jwgmeligmeyling
Copy link

@jwgmeligmeyling jwgmeligmeyling commented May 23, 2015

Thanks for the response, I will try that!

@iGEL
Copy link

@iGEL iGEL commented Jun 3, 2016

@thaJeztah That solution is not really satisfying as it breaks portability of the container.

@cpuguy83
Copy link
Collaborator

@cpuguy83 cpuguy83 commented Jun 3, 2016

If you are mounting files/dirs from the host, this is by definition non-portable.

@iGEL
Copy link

@iGEL iGEL commented Jun 3, 2016

Well, with docker-compose and the current path it is 😉

Ok, It's probably something that should be done in docker-compose if it isn't already.

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Jun 3, 2016

With "non" portable, @cpuguy83 means that you cannot start the container on a "random" host, without first creating the files and folders it needs for the bind-mount. (e.g., you cannot reschedule such a container to a different host in a Swarm cluster)

@chadfurman
Copy link

@chadfurman chadfurman commented Nov 12, 2016

So this issue kind of stagnated. I only plan on using Docker for local development, currently. That said, I plan on cloning down the git repo, running docker-compose up and having a development environment. Cool beans.

However, my web container does a gulp build resulting in all of my assets being owned by root and not being accessible. There should be a straight-forward way around this.

@cpuguy83
Copy link
Collaborator

@cpuguy83 cpuguy83 commented Nov 14, 2016

@chadfurman Not sure I follow.
You are running gulp build as the root user and as such the files are owned by root?

@chadfurman
Copy link

@chadfurman chadfurman commented Nov 14, 2016

@cpuguy83 I was running "gulp build" inside my container. As such, all files it built were owned by root because my container's default user was "root". There should be an easy way of making the container user the same user as the person who ran, for example, docker-compose up

I ended up running gulp build locally outside of the docker container and sharing the resulting dist/ files with the container

@cpuguy83
Copy link
Collaborator

@cpuguy83 cpuguy83 commented Nov 14, 2016

@chadfurman Something like this might work if you are working on Linux and docker is on the same machine. But otherwise it would just not be possible.
You can specify the user you want the container to start with manually.

Docker4Mac does uid/gid translation at the filesystem layer when mounting from the Mac into the container. This is outside of the core of docker, though.

@chadfurman
Copy link

@chadfurman chadfurman commented Nov 14, 2016

@cpuguy83 lots of developers use Linux and docker on the same machine.

I'm guessing you're talking about https://docs.docker.com/engine/reference/builder/#/user which needs to be built into the image?

Seems like a run-time "run as this user" setting would be helpful. Though, I can respect that risk-value proposition is not horribly enticing.

@cpuguy83
Copy link
Collaborator

@cpuguy83 cpuguy83 commented Nov 14, 2016

@chadfurman docker run supports --user, and I believe compose supports the same option in the yaml format.

@cpuguy83 cpuguy83 added this to the 1.13.0 milestone Nov 14, 2016
@cpuguy83 cpuguy83 removed this from the 1.13.0 milestone Nov 14, 2016
@leopoldodonnell
Copy link

@leopoldodonnell leopoldodonnell commented Jan 18, 2018

Its almost never a good idea to run your container as root.
The following will work for a lot applications

RUN addgroup {your group args} |
  && adduser {your user args}

USER {your-user}

RUN mkdir {directory you want to mount}

VOLUME ["{directory you want to mount}"]

Then you should be able to mount a host directory or a docker volume that you can write to.

Here's a simple alpine example that demonstrates the ability to write to a host directory from a non-root user...

FROM alpine

RUN addgroup -S app \
    && adduser -S -G app -h /home/app -D app

USER app
RUN mkdir /home/app/mount-data
VOLUME ["/home/app/mount-data"]
WORKDIR /home/app
$ docker build --rm -t mount-test .
$ mkdir mount-data
$ ls
-rw-r--r--@ 1 me  staff  171 Jan 18 10:19 Dockerfile
drwxr-xr-x  2 me  staff   64 Jan 18 10:19 mount-data/
$ docker run --rm -ti -v $PWD/mount-data:/home/app/mount-data mount-test /bin/sh
~ $ ls -l
total 0
drwxr-xr-x    2 app      app             64 Jan 18 15:19 mount-data
~ $ echo world > mount-data/hello
~ $ exit
$ cat mount-data/hello
world
$
@iamsoorena
Copy link

@iamsoorena iamsoorena commented Jan 20, 2018

my problem has another darker side, when I run docker with -u option, I can not install dependencies with yarn since yarn is installed as root user in most production ready images on docker hub.
so I should run docker as root to be able to use yarn but I should run docker commands as non-root user to be able to delete theme from outside of docker container(inside the volume) this is a serious problem.
my only solution is to chmod from inside docker container for each file and folder created by docker user and this is a real nightmare.

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Jan 20, 2018

since yarn is installed as root user in most production ready images on docker hub.

If these are official images, I suggest opening a ticket

shesek added a commit to ElementsProject/lightning-charge that referenced this issue Jan 20, 2018
- Add instructions to run docker with `--user <uid>`, so that files
  created within the container are owned by the user instead of root.

  See moby/moby#3124

- Move bitcoind, lightningd and charged data files out of /root
  and into /data, so that they could be accessed by non-root users
  within the container.
shesek added a commit to ElementsProject/lightning-charge that referenced this issue Jan 20, 2018
- Add instructions to run docker with `--user <uid>`, so that files
  created within the container are owned by the user instead of root.

  See moby/moby#3124

- Move bitcoind, lightningd and charged data files out of /root
  and into /data, so that they could be accessed by non-root users
  within the container.
@Vanuan
Copy link

@Vanuan Vanuan commented Jan 20, 2018

Have you tried echoing $HOME. I think it's not being set automatically with -u.

@Vanuan
Copy link

@Vanuan Vanuan commented Jan 20, 2018

so I should run docker as root to be able to use yarn but I should run docker commands as non-root user

When you say "docker" do you actually mean "container"? When you say "docker commands" do you mean "commands inside container?"

@leopoldodonnell
Copy link

@leopoldodonnell leopoldodonnell commented Jan 20, 2018

@iamsoorena - if you are indeed trying to perform a global install via yarn on a running container, you're going to have the same issue you'd have on any server where you aren't root (you launched as a different user). You'll need to install non-global packages into a hierarchy where your user has permissions. This is something that I do frequently when I use a container for development against my local OS X disk.

If what you really want to do, is to have an container image that has some yarn packages installed, I'd recommend that your just extend the image with your own additions. If the package you're using has already set the USER to something other than root, your can reset the user again, install your stuff and set it back to root.

@ebuildy
Copy link

@ebuildy ebuildy commented Oct 15, 2018

@bdurrow but the user doesnt exist inside the container, this can be problematic for some application that lookup user from UID. (Apache Spark / Hadoop in my case).

As a workaround now, we share a dynamic /etc/passwd file :/

Why Docker is not changing the /etc/passwd file as it do for /etc/hosts file?

@airtonix
Copy link

@airtonix airtonix commented Oct 7, 2020

@leopoldodonnell

docker run --rm -ti -v $PWD/mount-data:/home/app/mount-data mount-test /bin/sh

Doesn't work:

test $ cat .\Dockerfile
FROM alpine

RUN addgroup -S app \
    && adduser -S -G app -h /home/app -D app

USER app
RUN mkdir /home/app/mount-data
VOLUME ["/home/app/mount-data"]
WORKDIR /home/app
test $ docker build --rm -t mount-test .
[+] Building 1.1s (8/8) FINISHED
 => [internal] load build definition from Dockerfile                                                    0.0s
 => => transferring dockerfile: 32B                                                                     0.0s
 => [internal] load .dockerignore                                                                       0.1s
 => => transferring context: 2B                                                                         0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                        1.0s
 => [1/4] FROM docker.io/library/alpine@sha256:185518070891758909c9f839cf4ca393ee977ac378609f700f60a77  0.0s
 => CACHED [2/4] RUN addgroup -S app     && adduser -S -G app -h /home/app -D app                       0.0s
 => CACHED [3/4] RUN mkdir /home/app/mount-data                                                         0.0s
 => CACHED [4/4] WORKDIR /home/app                                                                      0.0s
 => exporting to image                                                                                  0.0s
 => => exporting layers                                                                                 0.0s
 => => writing image sha256:6db84b124bcedadbb647da8dc9b17b99271e66c1dbe22e9f97418563c9ef2e24            0.0s
 => => naming to docker.io/library/mount-test                                                           0.0s
test $ mkdir mount-data   


    Directory: C:\Users\zenobius\Desktop\test


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         10/7/2020   7:39 PM                mount-data


test $ docker run --rm -ti -v $PWD/mount-data:/home/app/mount-data mount-test /bin/sh
~ $ ls -l
total 0
drwxrwxrwx    1 root     root           512 Oct  7 09:09 mount-data
~ $ :(
@noahjahn
Copy link

@noahjahn noahjahn commented Mar 19, 2021

Man, this is confusing. I feel like this is a legitimate problem. I've tested the following on:
macOS BigSur v11.2.2 with:

  • Docker Desktop v3.2.2
  • Engine v20.10.5

AND a Windows 10 20H2 build 19042.867 computer with:

  • Docker Desktop v3.2.2
  • Engine v20.10.5
  • WSL 2 (Ubuntu 20.04)

For a very simple test, let's say there is a configuration directory on my host user's home directory that I want a running container to be able to modify. Let's call this directory ~/.conf. If you're testing this yourself, make this directory in your user profile with mkdir ~/.conf.

Here is a very simple Dockerfile to add and use a non-root user:

FROM alpine:latest

RUN addgroup -S appuser && adduser -S appuser -G appuser

USER appuser
WORKDIR /home/appuser

Okay, let's build this image:

docker build -f Dockerfile -t app .

Now, let's run the image interactively, bind mounting the ~/.conf directory on the host machine to the /home/appuser/.conf in the container:

docker run -it -v "$HOME/.conf":/home/appuser/.conf app /bin/sh

In the container, running ls -al shows that the bind mounted directory /home/appuser/.conf is owned by root. The group is also set as root:

~ $ ls -al
total 16
drwxr-sr-x    1 appuser  appuser       4096 Mar 19 13:50 .
drwxr-xr-x    1 root     root          4096 Mar 19 13:47 ..
-rw-------    1 appuser  appuser          7 Mar 19 13:50 .ash_history
drwxr-xr-x    5 root     root           160 Mar 17 13:50 .conf

Now, and here's the weird thing, running ls -al /home/appuser/.conf > /dev/null actually CHANGES the owner and group to be the correct user and group who should have access to the /home/appuser/.conf directory.

Here is the result of ls -al again after running the previous command:

~ $ ls -al
total 16
drwxr-sr-x    1 appuser  appuser       4096 Mar 19 13:50 .
drwxr-xr-x    1 root     root          4096 Mar 19 13:47 ..
-rw-------    1 appuser  appuser         53 Mar 19 13:52 .ash_history
drwxr-xr-x    5 appuser  appuser        160 Mar 17 13:50 .conf
~ $ 

Can someone explain what is happening here? This seems like incorrect behavior.

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Mar 19, 2021

@noahjahn that is indeed confusing. That looks like an issue with Docker Desktop, and it's best to report that one in either the https://github.com/docker/for-win or https://github.com/docker/for-mac issue tracker.

What I suspect is happening is that some caching is happening; on Docker Desktop, some "magic" is in place to ignore the actual ownership, and instead trick the container's user to think it's the owner. This was done to allow accessing your files in any container (irregardless as what user the container is running), without having to change the permissions of the files on your host (what is needed on a plain Linux situation).

To demonstrate; create a directory for testing, and create a file in it;

mkdir bla && cd bla
touch some-file.txt

Check the owner and group of the file (looking at the numeric ID's; user- and group-name on linux are only "presentation"). In this case, the file is owned by my user-account; UID 501 and GID 20

ls -n

total 0
-rw-r--r--  1 501  20  0 Mar 19 15:50 some-file.txt

Now, run a container as user 123 and group 456, with that file bind-mounted in the container, and check the file-ownership:

docker run --rm -v $(pwd):/foo -u 123:456 alpine ls -n /foo
total 0
-rw-r--r--    1 123      456              0 Mar 19 14:50 some-file.txt

The process in the container sees itself as owner of the file (123:456)

Starting another container, now as user 234:567, and the same happens; that container also thinks it's the owner of the file;

docker run --rm -v $(pwd):/foo -u 234:567 alpine ls -n /foo
total 0
-rw-r--r--    1 234      567              0 Mar 19 14:50 some-file.txt

Even though the file on the host has not been modified:

ls -n

total 0
-rw-r--r--  1 501  20  0 Mar 19 15:50 some-file.txt

So, I suspect something in that magic is either caching something, or there is some delay in making it work.

@lubomirblazekcz
Copy link

@lubomirblazekcz lubomirblazekcz commented May 27, 2021

I have a similiar issue where running composer from docker https://hub.docker.com/_/composer installs dependencies as root on Windows under WSL2. Yet when I do this on MacOS, installed dependencies are under correct host user.

@noahjahn
Copy link

@noahjahn noahjahn commented May 27, 2021

@evromalarkey

I have a similiar issue where running composer from docker https://hub.docker.com/_/composer installs dependencies as root on Windows under WSL2. Yet when I do this on MacOS, installed dependencies are under correct host user.

I experienced a similar problem. I think it's a bug in Docker Desktop for MacOS. If you export UID then run docker run --rm -v "$(pwd)":/app --user $UID:$UID composer install it will work every time. This tells docker to run the command as the user with the user ID of your host machine.

--rm to remove the container when it exists
-v to bind mount the current directory (assuming this is where your composer.json lives) to /app in the container
--user to set the UID and GID for the specified command.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet