Nothing Special   »   [go: up one dir, main page]

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

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

mingfang opened this issue Oct 17, 2013 · 225 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.

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

@mfhepp
Copy link
mfhepp commented May 1, 2024

Reports of problems with write-access to volumes on the host with Docker, in particular in rootless mode and with a non-root container user, are all over the WWW. Because this was a hard blocker for my work, I took the time to analyze it in depth; for my findings and a 2024 solution, see

mamba-org/micromamba-docker#407 (comment)

@coldbloodx
Copy link

hit the same issue while using userns-remap mode.
hope docker add this feature soon :)

snev68 added a commit to snev68/cubicle that referenced this issue Aug 5, 2024
Having the work directory at a fixed known location in the environment is
a bit more convenient in many cases.

There's also an obscure reason why it helps Docker volume mounts. When you do a
Docker volume mount on a non-existing directory, it's owned by root. When you
do a Docker volume mount on a directory that exists in the image, it takes on
that directory's ownership. See <moby/moby#2259>.
It's hard to make the directory exist in the image when you can't predict its
name, so this change will help.
@AJGranowski
Copy link
AJGranowski commented Oct 1, 2024

Here's a workaround project I built if anyone's interested: Docker User Mirror

It's a pair of shell scripts that:

  1. Create mount source items on the host before Docker does (so they're owned by the current host user rather than root).
  2. Create a mirrored host user in the container at runtime.
  3. chown mount destination items in the container to the mirrored user.
  4. Step-down from root to the mirrored user to execute the command.
$ id
uid=1000(user) gid=1000(user) groups=1000(user)...

$ cat image/Dockerfile
FROM debian:latest
COPY entrypoint /entrypoint
ARG GOSU_VERSION=1.17
ARG SETPRIV_VERSION=2.40.1
ARG UTIL_LINUX_VERSION=2.39.3
RUN chmod +x /entrypoint && /entrypoint --setup
ENTRYPOINT ["/entrypoint", "--"]

$ docker build -q image/
sha256:db48660e27...

$ ./user-mirror docker run -it --rm -v test_volume:/mnt/test_volume db48660e27 sh

    $ id
    uid=1000(user) gid=1000(user) groups=1000(user)

    $ touch /mnt/test_volume/test_file
    $ ls -l /mnt/test_volume/test_file
    -rw-r--r-- 1 user user 0 Oct  1 05:46 /mnt/test_volume/test_file

Also works with compose:

$ docker compose build
$ ./user-mirror docker compose run --rm {service}

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