Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker volumes : specifying permissions using mount options

I'm trying to use a named volume mounted in a Docker container, but get a Permission denied error when trying to create a file in the mounted folder. So I'm trying to use mount options when creating my volume, but that does not work as I want.

Introduction

I'm totally aware that when mounting a volume (created by docker volume create my_named_volume) with the option -v my_named_volume:/home/user/test or --mount type=volume,source=my_named_volume,target=/home/user/test), the folder inside the container (/home/user/test will be owned by root user, even if /home/user belongs to an user user created in my Dockerfile. If I run :

docker run --rm \
    --name test_named_volume \
    --mount type=volume,source=my_named_volume,target=/home/user/test \
    test_named_volume \
    su user -c "touch /home/user/test/a"

Then I get :

touch: cannot touch '/home/user/test/a': Permission denied

I'm understanding that. That's why I'm trying to use mount options when creating my volume.

mount options

I'm specifying an uid when creating my volume, in order to make my user user able to create a file in that volume :

docker volume create my_named_volume \
    --opt o=uid=1000

1000 is the uid of the user user created in my Dockerfile :

FROM    debian:jessie

ENV     HOME /home/user

RUN     useradd \
            --create-home \
            --home-dir $HOME \
            --uid 1000 \
            user \
 &&     chown -R user:user $HOME

WORKDIR $HOME

But when running my container (with the same command docker run defined above), I'm getting an error (missing device in volume options) :

docker: Error response from daemon: error while mounting volume '/var/lib/docker/volumes/my_named_volume/_data': missing device in volume options.

From the docs, I see that options --device and --type are missing from my volume creation :

docker volume create my_named_volume \
    --opt device=??? \
    --opt type=??? \
    --opt o=uid=1000

But I cannot see why I must give these options. device needs to be a block device, and from what I read, type should be something like ext4. But what I want is basically just set the uid option to my volume. It looks like creating a block device should work, but it seems too much configuration for a "simple" problem.

I have tried to use tmpfs for device and type, that works fine (file /home/user/test/a is created)... until my container is stopped (the data is not persisted, and that's logical because it's tmpfs). I want to persist that data written in the volume when the container exits.

What is the simplest way to specify permissions when mounting a named volume in a container? I don't want to modify my Dockerfile to use some magic (entrypoint that chown and then execute the command for example). It seems possible using mount options, I feel like I'm close to the solution, but maybe I'm in the wrong way.

like image 824
norbjd Avatar asked Jul 21 '18 13:07

norbjd


People also ask

What is the best way to manage permissions for Docker shared volumes?

"you can just use the data container as a "reference/handle" and set the ownership/perms in another container via chown in an entrypoint"...

What is difference between mount and volume in Docker?

The most notable difference between the two options is that --mount is more verbose and explicit, whereas -v is more of a shorthand for --mount . It combines all the options you pass to --mount into one field. On the surface, both commands create a PostgreSQL container and set a volume to persist data.

What does mounting a volume mean in Docker?

The VOLUME command will mount a directory inside your container and store any files created or edited inside that directory on your hosts disk outside the container file structure, bypassing the union file system.


1 Answers

Not entirely sure what your issue is, but this worked for me:

docker run --name test_named_volume \
  --mount type=volume,source=test_vol,target=/home/user \
  --user user \
  test_named_volume touch /home/user/a

I think where you could have gone wrong is:

  1. Your mount target is /home/user/test has not been created yet, since the useradd command in your Dockerfile only creates $HOME (/home/user). So docker creates the directory within the container with root permissions.

  2. You were not using the --user flag in docker run to run the container as the specified user.

like image 87
moebius Avatar answered Oct 02 '22 04:10

moebius