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

Add ability to mount volume as user other than root #2259

Open
mingfang opened this issue Oct 17, 2013 · 168 comments
Open

Add ability to mount volume as user other than root #2259

mingfang opened this issue Oct 17, 2013 · 168 comments

Comments

@mingfang
Copy link

@mingfang mingfang commented Oct 17, 2013

Use case: mount a volume from host to container for use by apache as www user.
The problem is currently all mounts are mounted as root inside the container.
For example, this command
docker run -v /tmp:/var/www ubuntu stat -c "%U %G" /var/www
will print "root root"

I need to mount it as user www inside the container.

@jpetazzo
Copy link
Contributor

@jpetazzo jpetazzo commented Oct 18, 2013

If you chown the volume (on the host side) before bind-mounting it, it will work.
In that case, you could do:

mkdir /tmp/www
chown 101:101 /tmp/www
docker run -v /tmp/www:/var/www ubuntu stat -c "%U %G" /var/www

(Assuming that 101:101 is the UID:GID of the www-data user in your container.)

Another possibility is to do the bind-mount, then chown inside the container.

@crosbymichael
Copy link
Contributor

@crosbymichael crosbymichael commented Nov 28, 2013

@mingfang Will chown not work for you ?

@bfirsh
Copy link
Contributor

@bfirsh bfirsh commented Jan 17, 2014

It would be useful to have a shortcut for this. I often find myself writing run scripts that just set the permissions on a volume:

https://github.com/orchardup/docker-redis/blob/07b65befbd69d9118e6c089e8616d48fe76232fd/run

@aldanor
Copy link

@aldanor aldanor commented Feb 18, 2014

What if you don't have the rights to chown it?

@cpuguy83 cpuguy83 mentioned this issue Jun 18, 2014
7 of 12 tasks complete
@iwinux
Copy link

@iwinux iwinux commented Jun 26, 2014

Would a helper script that chown the volume solve this problem? This scirpt can be the ENTRYPOINT of your Dockerfile.

@SvenDowideit
Copy link
Contributor

@SvenDowideit SvenDowideit commented Jul 8, 2014

Can I say no - forcing users to add a helper script that does

#!/bin/sh
chown -R redis:redis /var/lib/redis
exec sudo -u redis /usr/bin/redis-server

(thanks @bfirsh for your eg)

is pretty terrible.

It means that the container has to be started as root, rather than running as the intended redis user. (as @aldanor alluded to )

and it means a user can't do something like:

docker run -v /home/user/.app_cfg/ -u user application_container application :(

@SvenDowideit
Copy link
Contributor

@SvenDowideit SvenDowideit commented Jul 8, 2014

There is one way to make it work, but you need to prepare ahead of time inside your Dockrfile.

RUN mkdir -p /var/lib/redis ; chown -R redis:redis /var/lib/redis
VOLUME ["/var/lib/redis"]
ENTRYPOINT ["usr/bin/redis-server"]
USER redis

(I didn't test this example, I'm working on a chromium container that then displays on a separate X11 container that .... )

@tianon
Copy link
Member

@tianon tianon commented Jul 10, 2014

And of course that method only works for direct new volumes, not bind
mounted or volumes-from volumes. ;)

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Jul 14, 2014

Additionally, multiple containers using volumes-from will have different uid/gid for the same user, which complicates stuff as well.

@frankamp
Copy link

@frankamp frankamp commented Aug 7, 2014

@SvenDowideit @tianon that method doesn't work either. Full example:

FROM ubuntu
RUN groupadd -r redis    -g 433 && \
useradd -u 431 -r -g redis -d /app -s /sbin/nologin -c "Docker image user" redis 
RUN mkdir -p /var/lib/redis
RUN echo "thing" > /var/lib/redis/thing.txt
RUN chown -R redis:redis /var/lib/redis
VOLUME ["/var/lib/redis"]
USER redis
CMD /bin/ls -lah /var/lib/redis

Two runs, with and without a -v volume:

bash-3.2$ docker run -v `pwd`:/var/lib/redis voltest 
total 8.0K
drwxr-xr-x  1 root root  102 Aug  7 21:30 .
drwxr-xr-x 28 root root 4.0K Aug  7 21:26 ..
-rw-r--r--  1 root root  312 Aug  7 21:30 Dockerfile
bash-3.2$ docker run  voltest 
total 12K
drwxr-xr-x  2 redis redis 4.0K Aug  7 21:30 .
drwxr-xr-x 28 root  root  4.0K Aug  7 21:26 ..
-rw-r--r--  1 redis redis    6 Aug  7 21:26 thing.txt
bash-3.2$ 
@andrewmichaelsmith
Copy link

@andrewmichaelsmith andrewmichaelsmith commented Nov 13, 2014

We're hitting an issue that would be solved by this (I think). We have an NFS share for our developer's home directories. Developers want to mount /home/dev/git/project in to Docker but cannot because we have Root Squash enabled.

This forbids root from accessing /home/dev/git/project so when I try and run docker mounting /home/dev/git/project I get an lstat permission denied error.

@cpuguy83
Copy link
Collaborator

@cpuguy83 cpuguy83 commented Nov 13, 2014

@frankamp This is because docker's current preference is to not modify host things which are not within Docker's own control.

Your "VOLUME" definition is being overwritten by your -v pwd`:/var/lib/reds`.
But in your 2nd run, it is using a docker controlled volume, which is created in /var/lib/docker. When the container starts, docker is copying the data from the image into the volume, then chowning the volume with the uid:gid of the dir the volume was specified for.

I'm not sure there is much that can be done here, and unfortunately bind mounts do not support (as far as I can tell) mounting as a different uid/gid.

@ebuchman
Copy link

@ebuchman ebuchman commented Jun 13, 2015

My solution to this was to do what SvenDowideit did above (create new user and chown up front in dockerfile), but then instead of mounting the host volume, use a data-only container, and copy the host volume I wanted to mount into the container with tar cf - . | docker run -i --volumes-from app_data app tar xvf - -C /data. This will become a tad easier once #13171 is merged (and docker cp works both ways), but perhaps it could become an alternative to -v host_dir:container_dir, ie. maybe -vc host_dir:container_dir, (vc for volume-copy), wherein the host_dir's contents would get copied into the data container. Though I can't say I understand why/how the copied files inherit the container user's permissions, from what I can tell they do, and this is the only reasonable solution I've managed to come up with that doesn't destroy portability.

@jsdevel
Copy link

@jsdevel jsdevel commented Dec 7, 2015

What about acl?

@calvix
Copy link

@calvix calvix commented Jan 6, 2016

Is there any fix or workaround? I run into same issue with OpenShift, mounted folder is owned by root:root and precreated images wont work.

@brikis98
Copy link

@brikis98 brikis98 commented Jan 21, 2016

I'm looking for a workaround too. If all mounted volumes are owned by root, it makes it impossible to run your Docker containers with any user other than root.

@dreamcat4
Copy link

@dreamcat4 dreamcat4 commented Jan 21, 2016

Well you can try s6-overlay. It includes features which are specifically targeted to help to work-around these kinds of problems.

@brikis98
Copy link

@brikis98 brikis98 commented Jan 21, 2016

@dreamcat4: Thanks for the pointer. The fixing ownership & permissions seems like an interesting workaround, but wouldn't I have to run my Docker container as root for that to work?

@dreamcat4
Copy link

@dreamcat4 dreamcat4 commented Jan 21, 2016

@brikis98 Yes that is true. However s6-overlay also has yet another feature, which allows you to drop the permissions back again when launching your servers / daemons.

@brikis98
Copy link

@brikis98 brikis98 commented Jan 21, 2016

@dreamcat4 Ah, gotcha, thanks.

tsunamaru added a commit to tsunamaru/spodlivoibot that referenced this issue Nov 13, 2020
@prologic
Copy link
Contributor

@prologic prologic commented Nov 13, 2020

As per @dreamcat4 's last comment, has anyone made a new attempt to see what the status of this is? Do we have support in the Kernel for remappable uids and gids now? What's the overall status here?

@acheronfail
Copy link

@acheronfail acheronfail commented Nov 13, 2020

I've used Linux User Namespaces to perfectly solve this issue. Works exactly the same (AFAICT) as the other platforms (container sees bind mounted volume as root, host sees it as the user who's running docker).

Guide is here: https://www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/

@thockin
Copy link
Contributor

@thockin thockin commented Jan 21, 2021

This issue came up on a tool I manage, and I am sad to see this bug still open 7 years later. Does the kubernetes model work here?

Specifically, what Kubernetes does is make sure that volumes are group-writable by a configurable GID, then makes sure that GID is in the supplemental groups list for each accessing container.

How would this translate to raw docker? Hand-waving ensues:

What if we could do something like docker run -v volname:/vol:group=12345 ... which would make the volume group-owned by 12345 and group-writeable. we can debate whether a recursive chgrp and chmod is necessary or simply the top-level. Or maybe this is only available in docker volume create. Either way, the volume is now group-accessible.

Now make it possible to ADD a supplemental group to a docker run. For many users the existing -u :<gid> works, but Linux has a supplemental groups list for a reason.

Now a volume can be associated with a GID and any container can use that GID to access the volume.

@DXist
Copy link

@DXist DXist commented Jan 21, 2021

Group owned by 12345 is not enough for new files - setgid bit is needed to maintain the chosen group ownership for new files in volume directory tree.

With ACLs it's possible to configure more complex permission defaults - like multiple groups or users with write access.

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Jan 21, 2021

Now make it possible to ADD a supplemental group to a docker run

I think that should already work through the --group-add option;

      --group-add list                 Add additional groups to join
$ docker run --rm -u 123:456 --group-add 12345 --group-add 2345 busybox id
uid=123 gid=456 groups=2345,12345

Or maybe this is only available in docker volume create. Either way, the volume is now group-accessible.

I'd prefer that option over adding more options to the (already overloaded) -v .... syntax. That said; this would likely depend on the volume driver that's used; would work for the "local" volume driver, but likely not for other ones.

@willzhang
Copy link

@willzhang willzhang commented Feb 5, 2021

same problems
bitnami image are non-root image, if you run as root it can not start successful

docker run -d --name tomcat-app \
  --restart always \
  -p 8003:8080 \
  -v /root/wars/:/bitnami/tomcat/data \
  bitnami/tomcat 
@rodrigoaguilera
Copy link

@rodrigoaguilera rodrigoaguilera commented Feb 14, 2021

There is some hope for a linux feature called IDMAPPED that will make it easy for docker to implement a mount with a mapping

https://www.phoronix.com/scan.php?page=news_item&px=IDMAPPED-Mounts-Linux-5.12

@marcosnils
Copy link

@marcosnils marcosnils commented Feb 24, 2021

^ I've been talking with @justincormack on bringing this into docker. There's already a WiP in containerd to implement this containerd/containerd#4734

I guess what's missing from moby's side is define what the UX is going to be. Since using this will require the container to be created using userns as well.

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Feb 24, 2021

Yes, I saw that "idmapped mounts" was merged today (which is good news!); torvalds/linux@7d6beb7

We were also discussing it already internally. I'd have to dive into the options a bit further myself, but some things we were discussing

  • containers / software that starts as "privileged" user, and (after initialisation) falls back to a non-privileged user. Some of those cases were because of using privileged ports, and would no longer be needed since #41030, but there may be other cases
  • for the above, depending on the situation, you'd want to map the volume to either the container's main user (root?), or to the unprivileged container user

Since using this will require the container to be created using userns as well.

Running the container with userns would already work today (if the mapping local user -> remapped -> container user), although we only support a single mapping, so if different containers run with different (remapped) users, then permissions could still be an issue

The interesting question of course (I'm not sure if it's supported by idmapped mounts) is the reverse; situations where the container runs as actual root (no userns), but you want (e.g. in a developer situation) to bind-mount a path from the host and have files written as root in the container to be owned by local user outside of the container.

I guess there's quite some options / combinations that may exist (rootless, non-rootless, user-namespaces, multiple users), that would have to be looked into as to what the best approach is.

... and "main" distributions to be on a recent kernel version that supports it.

@StarpTech
Copy link

@StarpTech StarpTech commented Mar 9, 2021

We use --volumes-from and -v and could solve it gracefully with that workaround. In Gitlab it runs with root but locally with the default user.

read -r -d '' command <<- CMD
	chown -R $(id -u):$(id -g) $PACKAGE_DIR
	cd $PACKAGE_DIR
	$DOCKER_CMD
CMD

docker run --rm ${VOLUME_OPTION} ${TESTSDK_PROJECT}_runner:latest bash -c "${command}"
@mo-saeed
Copy link

@mo-saeed mo-saeed commented Mar 10, 2021

I am using DIND rootless and I have an issue that the volumes are always mounted with root user ownership, it seems that user map doesn't work with rootless containers. do you have any solutions for that?

@jdmarshall
Copy link

@jdmarshall jdmarshall commented Apr 2, 2021

Another use case that I don't think is getting a lot of visibility here is that since volumes can't be mounted during 'docker build', it's possible that someone is running the image solely to extract an artifact from the image at build or deployment time (eg, to upload assets to a CDN) in which case these elaborate workarounds are quite difficult to manage.

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Apr 2, 2021

@jdmarshall you may be interested in #16079 (comment) for that

@jpierson
Copy link

@jpierson jpierson commented Apr 30, 2021

I'm also on Windows so the UID/GID matching stuff seems to be lost on me in my situation. I've tried @nagstaku's solution below but it didn't seem to work for me. After doing docker run with /bin/bash as the command and running the following commands as root, it looks like all of the files mounted and then linked under /home/nonroot/mymaven are still shown as owned by root. Additionally, typical commands such as mvn clean fail since it is unable to delete build artifact files under the corresponding module /target directories.

ln -s -T /usr/src/mymaven /home/nonroot/mymaven
chown -Rh nonroot:nonroot /home/nonroot/mymaven

#2259 (comment)

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

Successfully merging a pull request may close this issue.

None yet