Docker Community Forums

Share and learn in the Docker community.

Docker mounted volume permission issues

Hey all, I have been having permission issues with mounted volumes on my docker container and would like some help. I have tried the chown method, but even with all IDs being the same the bash script that is executed inside of the container has permission issues writing to the volume. I have made sure that the userID and groupID for both the file system (that is mounted as a volume to the container) and the container are the same.

Any help on this would be appreciated, fairly new docker user here.

IDs outside of the container, just on the file system:
[millebri@exahead1 lifted_over]$ id
uid=5507(millebri) gid=2069(ConradLab) groups=2069(ConradLab),2084(primeseqreader),3010(HPCUsers),3759(accessexacloud),3777(docker),3984(accessmonkeydo),5507(millebri)

Running the container (interactively this time):
sudo /opt/acc/sbin/exadocker run
-i
-t
–user “(id -u):(id -g)”
–rm
-v /home/groups/ConradLab:/ConradLab
millebri/variant_calling_pipeline:latest

IDs inside of the container:
I have no name!@b66ad0ea727d:/home/newuser$ id
uid=5507 gid=2069 groups=2069

Error message returned (line 22 is where I make a file and write it to the volume)
vcf_to_bed.sh: line 22: EGAF00000498465_hg38liftover_snv_tmp.bed: Permission denied

What else does docker need to know that this is the correct UID and GID?!

I believe the canonical way to solve this is by using data-only containers. With this approach, all access to the volume data is via containers that use -volumes-from the data container, so the host uid/gid doesn’t matter.

For example, one use case given in the documentation is backing up a data volume. To do this another container is used to do the backup via tar, and it too uses -volumes-from in order to mount the volume. So I think the key point to grok is: rather than thinking about how to get access to the data on the host with the proper permissions, think about how to do whatever you need – backups, browsing, etc. – via another container. The containers themselves need to use consistent uid/gids, but they don’t need to map to anything on the host, thereby remaining portable.

This is relatively new for me as well but if you have a particular use case feel free to comment and I’ll try to expand on the answer.

UPDATE: For the given use case in the comments, you might have an image some/graphite to run graphite, and an image some/graphitedata as the data container. So, ignoring ports and such, the Dockerfile of image some/graphitedata is something like:

FROM debian:jessie

add our user and group first to make sure their IDs get assigned consistently, regardless of other deps added later

RUN groupadd -r graphite
&& useradd -r -g graphite graphite
RUN mkdir -p /data/graphite
&& chown -R graphite:graphite /data/graphite
VOLUME /data/graphite
USER graphite
CMD [“echo”, “Data container for graphite”]
Build and create the data container:

docker build -t some/graphitedata Dockerfile
docker run --name graphitedata some/graphitedata
The some/graphite Dockerfile should also get the same uid/gids, therefore it might look something like this:

FROM debian:jessie

add our user and group first to make sure their IDs get assigned consistently, regardless of other deps added later

RUN groupadd -r graphite
&& useradd -r -g graphite graphite

… graphite installation …

VOLUME /data/graphite
USER graphite
CMD ["/bin/graphite"]
And it would be run as follows:

docker run --volumes-from=graphitedata some/graphite
Ok, now that gives us our graphite container and associated data-only container with the correct user/group (note you could re-use the some/graphite container for the data container as well, overriding the entrypoing/cmd when running it, but having them as separate images IMO is clearer).

Now, lets say you want to edit something in the data folder. So rather than bind mounting the volume to the host and editing it there, create a new container to do that job. Lets call it some/graphitetools. Lets also create the appropriate user/group, just like the some/graphite image.

FROM debian:jessie

add our user and group first to make sure their IDs get assigned consistently, regardless of other deps added later

RUN groupadd -r graphite
&& useradd -r -g graphite graphite
VOLUME /data/graphite
USER graphite
CMD ["/bin/bash"]
You could make this DRY by inheriting from some/graphite or some/graphitedata in the Dockerfile, or instead of creating a new image just re-use one of the existing ones (overriding entrypoint/cmd as necessary).

Now, you simply run:

docker run -ti --rm --volumes-from=graphitedata some/graphitetools
and then vi /data/graphite/whatever.txt. This works perfectly because all the containers have the same graphite user with matching uid/gid.

Since you never mount /data/graphite from the host, you don’t care how the host uid/gid maps to the uid/gid defined inside the graphite and graphitetools containers. Those containers can now be deployed to any host, and they will continue to work perfectly.

The neat thing about this is that graphitetools could have all sorts of useful utilities and scripts, that you can now also deploy in a portable manner.

UPDATE 2: After writing this answer, I decided to write a more complete blog post about this approach. I hope it helps.

UPDATE 3: I corrected this answer and added more specifics. It previously contained some incorrect assumptions about ownership and perms – the ownership is usually assigned at volume creation time i.e. in the data container, because that is when the volume is created. See this blog. This is not a requirement though – you can just use the data container as a “reference/handle” and set the ownership/perms in another container via chown in an entrypoint, which ends with gosu to run the command as the correct user. If anyone is interested in this approach, please comment and I can provide links to a sample using this approach.