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 · 112 comments

Comments

Projects
None yet
@mingfang
Copy link

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Member

crosbymichael commented Nov 28, 2013

@mingfang Will chown not work for you ?

@bfirsh

This comment has been minimized.

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

This comment has been minimized.

Copy link

aldanor commented Feb 18, 2014

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

@cpuguy83 cpuguy83 referenced this issue Jun 18, 2014

Closed

Collected issues with Volumes #6496

7 of 12 tasks complete
@iwinux

This comment has been minimized.

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

jsdevel commented Dec 7, 2015

What about acl?

@calvix

This comment has been minimized.

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

brikis98 commented Jan 21, 2016

@dreamcat4 Ah, gotcha, thanks.

@cpuguy83

This comment has been minimized.

Copy link
Contributor

cpuguy83 commented Jan 12, 2018

@mwaeckerlin Why do you need to mount inside the container?

@mwaeckerlin

This comment has been minimized.

Copy link

mwaeckerlin commented Jan 12, 2018

Because I cannot specify a user/group with docker option -v.

The Idea specified above was: Bind-mount inside the container, then chown on the target should not change the source.

@cpuguy83

This comment has been minimized.

Copy link
Contributor

cpuguy83 commented Jan 12, 2018

@mwaeckerlin If you change it, it's changed everywhere. This is the crux of the problem in this issue.
Chowning/Chmoding a bind-mounted file/dir changes both places.

Also there is no need to be able to mount inside the container you can --mount type=bind,source=/foo,target=/bar

@mwaeckerlin

This comment has been minimized.

Copy link

mwaeckerlin commented Jan 12, 2018

Yes, I just tested it outside of docker, so the idea above is wrong.

The main problem, that I have often see in docker, is that the users, groups are not identical in different images, even when the same username or groupname exists in both, they often have different ids.

Here something like this would at least help in some cases: --mount type=bind,source=/foo,target=/bar,user=me,group=mine

@mwaeckerlin

This comment has been minimized.

Copy link

mwaeckerlin commented Jan 12, 2018

Any recommendations or best practices regarding this topic: shared volume user by different users in different images in docker swarm?

@cpuguy83

This comment has been minimized.

Copy link
Contributor

cpuguy83 commented Jan 12, 2018

  1. Don't share volumes
  2. Sync up your uid/gids
  3. Ensure permissions are permissive enough for all that are sharing
  4. Use fuse mounts on the host to bind to different uid/gid's for each container
@aairey

This comment has been minimized.

Copy link

aairey commented Jan 12, 2018

@tianon

This comment has been minimized.

Copy link
Member

tianon commented Jan 12, 2018

Using something like https://bindfs.org/ -- there's even at least one Docker volume plugin which already implements it (https://github.com/lebokus/docker-volume-bindfs is the first result I found via Google).

@solody

This comment has been minimized.

Copy link

solody commented Jan 21, 2018

i cant change permission after mounting the volume, is that any one get this?

@AndolsiZied

This comment has been minimized.

Copy link

AndolsiZied commented Jan 23, 2018

a workaround :
Adding this to Dockerfile
RUN echo "if [ -e container_volume_path ]; then sudo chown user_name container_volume_path; fi" >> /home/user_name/.bashrc
The ownership of the container_volume_path is changed after the volume has been mounted.

@colbygk

This comment has been minimized.

Copy link

colbygk commented Feb 8, 2018

Being able to map uid and gid seems like a mysterious missing element to docker volume handling. The path of least surprise would be to include it and the suggested fixes are clunky and harder to discover, while providing no best practices benefit:

Re:

  1. Don't share volumes
  • Good, but immaterial to the discussion on mapping uid/gid
  1. Sync up your uid/gids
  • That's what the functionality is intended to do, but without forcing a chown in a Dockerfile
  1. Ensure permissions are permissive enough for all that are sharing
  • This again relies on behavior defined in a Dockerfile, when it could be a simple mapping
  1. Use fuse mounts on the host to bind different uid/gid's for each container
  • Good advice, that also seems like yak-shaving.
@cpuguy83

This comment has been minimized.

Copy link
Contributor

cpuguy83 commented Feb 8, 2018

@colbygk

when it could be a simple mapping

That's the problem, it is not possible to do a "simple mapping" as it is not supported at the vfs layer.
Some filesystems provide the ability to map ownership (e.g. bindfs or nfs), but implementing this in the generic case is not currently possible.

@mwaeckerlin

This comment has been minimized.

Copy link

mwaeckerlin commented Feb 27, 2018

I need shared volumes e.g. in the following situation:

Shared Certificates

  • container 1 is a reverse-proxy that handles let's encrypt for all hosted domains
  • container 2 is an ldap server that also needs to provide the certificate of it's domain

solution: the image container 2 inherits from the same image than container 1, the common base image creates a common group, then both container have the same group access

Dockerfile of common base:

RUN groupadd -g 500 ssl-cert

letsencrypt-config.sh in the let's encrypt image:

chgrp -R ssl-cert /etc/letsencrypt

Dockerfile of mwaeckerlin/reverse-proxy:

RUN usermod -a -G ssl-cert www-data

Dockerfile of mwaeckerlin/openldap:

RUN usermod -a -G ssl-cert openldap

That's it.

borekb added a commit to versionpress/versionpress that referenced this issue May 13, 2018

Fixed permission problems by setting correct owners to folders and ru…
…nning tests under the www-data user always (no sudo). This is done a bit indirectly as Docker doesn't support mounting volumes as a non-root user (see moby/moby#2259), by creating a custom image `versionpress/wordpress:cli`. Newer Git version was necessary to install into the container anyway.
@ljay79

This comment has been minimized.

Copy link

ljay79 commented Jun 17, 2018

All of this illustrates on how to change userperms during entrypoint or during build process to have the entire docker run in a different user.

But maybe i miss a big point after searching the web for past 3 days.
None of above or otherwise linked recommendations and (workarounds) will work in any way.

All volumes mounted to a container are always owned by root:root inside the container. Regardsless if i change the owner upfront on the host with matching UID/GID or not.

I cant loose the feeling im being stupid trying to do something very very basic - from my point of view.

  • Windows 10 Pro 1803 (17134.112)
  • Docker for Windows 18.03.1-ce-win65 (17513)
  • Windows WSL with Hyper-V and Ubuntu

Trying to start a plain apache2 container where the document root is mounted to host so i am able to develop on php source code while immediately test it on the docker container.

root@win10:# docker run --rm -v /c/Users/<MyUser>/Development/www-data:/var/www/html -it httpd:2.4 /bin/bash

Inside the docker container, the directoy /var/www/html is always owned by root:root, so my php app wont ever be able to fopen, or write with any data inside that folder ever..
Nothing worked yet... :(

@binarymist

This comment has been minimized.

Copy link

binarymist commented Oct 19, 2018

For those searching for a reasonably elegant solution check out what @elquimista suggested here. I've tested this and is working nicely

@StanAngeloff

This comment has been minimized.

Copy link

StanAngeloff commented Nov 2, 2018

We've been using https://github.com/boxboat/fixuid#specify-paths-and-behavior-across-devices with luck. In addition it sets up a user inside the container to match a user on the host.

Here's an example configuration from the image:

$ cat /etc/fixuid/config.yml
user: lion
group: lion
paths:
  - /home/lion
  - /home/lion/.composer/cache
  - /tmp

and to run:

$ docker run --rm -it --init \
    -u 1000:1000 \
    -v `pwd`:/app \
    -v "$HOME/.composer/cache:/home/lion/.composer/cache" \
    --entrypoint='fixuid' \
    php:7.2-cli \
        /bin/bash
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment