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 · 222 comments
Open

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

mingfang opened this issue Oct 17, 2013 · 222 comments
Labels
area/api area/kernel area/volumes exp/expert kind/enhancement Enhancements are not bugs or new features but can improve usability or performance.

Comments

@mingfang
Copy link

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

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

@mingfang Will chown not work for you ?

@bfirsh
Copy link
Contributor

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 commented Feb 18, 2014

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

@iwinux
Copy link

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

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

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

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

@frankamp
Copy link

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

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
Member

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

@jessfraz jessfraz added bug exp/expert kind/enhancement Enhancements are not bugs or new features but can improve usability or performance. and removed Distribution labels Feb 26, 2015
@ebuchman
Copy link

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 commented Dec 7, 2015

What about acl?

@calvix
Copy link

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

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

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

@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

@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

@dreamcat4 Ah, gotcha, thanks.

@jdmarshall
Copy link

I recall that on a much earlier rev of docker desktop they were having problems with the filesystem glitching out under high I/O load, because essentially you have a virtual machine hosting docker, trying to access files from the host's host.

The group wisdom was that you would get faster and more stable behavior by using a network filesystem to access files on the physical machine. I wonder if that solution would work here too, and what the overhead would be.

@jdmarshall
Copy link

jdmarshall commented Dec 5, 2022

I would just like to point out, since it's been lost in the reply churn, that this solution mentioned early in the reply chain works well, when you can control the host operating system enough to have a stable user id across the cluster.

Doesn't work so good for tmpfs, but does fine for normal volumes.

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.

Our cluster is homogeneous, so I have a base image that a couple of services and a sidecar share, which among other things handles the UID/GID mapping.

@Clockwork-Muse
Copy link

"Yes, but actually no."

No, because what you normally want for a dev environment is that a specific host user is mapped to a specific container user (usually the same uid, as with podman's --userns keep-id option).

@ligix
Copy link

ligix commented Jan 15, 2023

Almost 10 years 🎉🥳🎉

@jdmarshall
Copy link

No, because what you normally want for a dev environment is that a specific host user is mapped to a specific container user (usually the same uid, as with podman's --userns keep-id option).

in a corporate environment every developer is going to potentially have a separate UID. And even if it starts the same, there’s always fun with people changing their names, lost or stolen machines and such.

That means custom config for every user which we tend to frown on. It’s bad for onboarding and a tripping hazard for everyone else.

@Clockwork-Muse
Copy link

No, because what you normally want for a dev environment is that a specific host user is mapped to a specific container user (usually the same uid, as with podman's --userns keep-id option).

in a corporate environment every developer is going to potentially have a separate UID. And even if it starts the same, there’s always fun with people changing their names, lost or stolen machines and such.

That means custom config for every user which we tend to frown on. It’s bad for onboarding and a tripping hazard for everyone else.

Normally with devcontainers, you don't have to worry about "other" users, only the initiating one. In most cases, the machine used will be their own, so won't have other users on it anyways. Outside of that, mounted volumes will usually come from their home directories.
The idea here is that you don't have config for each user - the devcontainer spec mostly handles in-container uid updates automatically, you just have to make sure the uid remap mechanism properly takes it into account. This is far easier with rootless setups (at least with podman), because then you don't have people stepping on each other at all.

@oerp-odoo
Copy link

Its also problematic when you use secrets that should be accessible by specific user. For example PGPASSFILE expects 0600 access, which if set would not make it available to non owners (and I don't see how to map it with other user, when mounting password file).

And that hack to know the UID/GID of your user and change ownership, does not look good. I want this to dynamically work in any host, not for specific user on some environment (as UID/GID might not match in all hosts).

@EugenKon
Copy link

To my mind it would be ideally: --mount type=bind,source=/host/dir,target=/app,perm=0777,owner=xxxx:yyyy. Where xxxx and yyyy are user and group inside container.

@polarathene
Copy link
Contributor

polarathene commented Sep 28, 2023

About half the time I need this feature just to handle tmpfs mounts properly, and here I am again devising a workaround for this issue. Of course I also discovered there's a bug in tmpfs-mode (mode is entirely ignored in the very reasonable scenario of clobbering a file with a mount point, and it changes the owner:group to root while preserving the original mode) which means I'm on Plan C. - Comment

As noted in the limitations section of tmpfs mount docs (this was added to docs in Feb 2023), you can set the UID/GID of what you'd expect it to be instead of the default 0:0: docker/compose#3425 (comment)

# Example

$ docker run --rm -it --tmpfs "/data:exec,uid=$(id -u),gid=$(id -g),mode=0644,size=1G" alpine ash
$ apk add exa

# Mode is correctly changed, so is the UID and GID:
$ exa --octal-permissions -ldgh /data
Octal Permissions Size User Group Date Modified Name
0644  drw-r--r--     - 1000 1000  28 Sep 23:03  /data

# Size is correctly applied:
$ df -h /data
tmpfs                     1.0G         0      1.0G   0% /data

This PR that didn't get merged additionally notes:

The supported mount options are the same as the Linux default mount flag.
If you do not specify any options, the system uses the default rw,noexec,nosuid,nodev,size=65536k options.

Not exactly, size is 50% of Docker host by default:

$ docker run --rm -it --tmpfs "/data" alpine ash

$ mount | grep /data
tmpfs on /data type tmpfs (rw,nosuid,nodev,noexec,relatime)
$ cat /proc/mounts | grep /data
tmpfs /data tmpfs rw,nosuid,nodev,noexec,relatime 0 0

$ df -h /data
Filesystem                Size      Used Available Use% Mounted on
tmpfs                     7.6G         0      7.6G   0% /data

Additionally the Docker docs on tmpfs incorrectly state:

In general, --mount is more explicit and verbose. The biggest difference is that the --tmpfs flag does not support any configurable options.

Clearly it does support options now as shown above.

M4rYu5 added a commit to M4rYu5/web-dev-practice that referenced this issue Dec 3, 2023
it's a volume, not a mount because I wasn't confortable using the user:root
and didn't want to go deeper in sysadmin stuff

can read more about difference between --mount and -v here: https://docs.docker.com/storage/volumes/#choose-the--v-or---mount-flag

rabbit hole here: moby/moby#2259
github-merge-queue bot pushed a commit to kurtosis-tech/kurtosis that referenced this issue Jan 8, 2024
## Description:
This allows users to change the user & group with which a container
starts

## Is this change user facing?
YES

## References (if applicable):
Closes #2000

Note this is a workaround to solve #2000 while
moby/moby#2259 remains open
@Michele971
Copy link

Executing my springboot project as a non-root?

I've been trying to run a Java JAR launcher as a non-root user for my Spring Boot project. I've already added the user and set the working directory accordingly. However, the project still seems to be running with root privileges.

Any suggestions on the best approach to ensure it runs as the designated user?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/api area/kernel area/volumes exp/expert kind/enhancement Enhancements are not bugs or new features but can improve usability or performance.
Projects
None yet
Development

No branches or pull requests