Mount "named volume" as non-root in Docker
Asked Answered
T

4

16

Is there any way to mount a named volume as a non-root user? I am trying to avoid having to run a chown in each Dockerfile but I need the mount to be writable by a non-root user to be able to write the artifacts created by a build in the image

This is what I'm trying

docker run --rm -it -v /home/bob/dev/:/src/dev -v builds:/mnt/build --name build hilikus/build /bin/bash

but for the second mount I get

[user@42f237282128 ~]$ ll /mnt
total 4
drwxr-xr-x 2 root root 4096 Sep 18 19:29 build

My other mount (/src/dev/) is owned by user, not by root so it gives what I need; however, I haven't been able to do the same with the named volume.

Tautonym answered 19/9, 2016 at 3:19 Comment(0)
S
5

The named volume initializes to the contents of your image at that location, so you need to set the permissions inside your Dockerfile:

$ cat df.vf-uid
FROM busybox
RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data

$ docker build -t test-vf -f df.vf-uid .
Sending build context to Docker daemon 23.06 MB
Step 1 : FROM busybox
 ---> 2b8fd9751c4c
Step 2 : RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data
 ---> Using cache
 ---> 41390b132940
Successfully built 41390b132940

$ docker run -v test-vol:/data --rm -it test-vf ls -alR /data
/data:
total 12
drwxr-xr-x    2 1000     root          4096 Sep 19 15:26 .
drwxr-xr-x   19 root     root          4096 Sep 19 15:26 ..
-rw-r--r--    1 1000     root            12 Aug 22 11:43 hello
Styrax answered 19/9, 2016 at 15:28 Comment(6)
Very strange, I've a similar Dockerfile as you, but I have this extra instructions VOLUME /data, when I do the docker run as you show, everything is back to root ownership (note that another difference is that my volume is empty at start, so I only change the volume folder ownership.Corabelle
I "took the bull by the horn" as we say here! I overlooked the documentation on Dockerfile it states Changing the volume from within the Dockerfile: If any build steps change the data within the volume after it has been declared, those changes will be discarded. I just had that! The VOLUME instruction was before I created the folder and set the permissions. It was simply discarded.Corabelle
@Corabelle I have a personal best practice to not mix Volumes with a Dockerfile. See my blog post for the full explanation, but you hit on one of the big issues already: boxboat.com/2017/01/23/volumes-and-dockerfiles-dont-mixStyrax
The added value of having them declared in the Dockerfile is mostly 2 things: it persists the data even if you forgot to provide volume in docker run (and one understand that named volumes are auto-created); wrappers can propose automatically users to create volumes by simply inspecting the image (no need for doc). But if you provide good docs, then those 2 points are not so relevant and can be considered optional. All this to tell you that yes I agree with your best practice, it brings more advantages (or less headaches).Corabelle
I seems to work for a named volume used in a single container, where I set the permissions in the Dockefile. But what if I use a named volume in two containers? Which Dockerfile or which image respectively would be responsible for the permissions of the volume?Surgical
@DarioSeidl whichever starts first, and once the volume is initialized it won't be initialized again by an update to the image or using the volume with a different image.Styrax
S
0

If you use the new --mount syntax instead of the old -v/--volume syntax it is supposedly possible to assign a uid to the volume's contents via docker volume create somename --opt -o=uid=1000 or something similar.

See https://docs.docker.com/engine/reference/commandline/volume_create/#driver-specific-options

I haven't fully tested this to run as non-root or using the dockremap dynamic user with the userns-map option but hope to soon.

Slapjack answered 2/5, 2018 at 18:41 Comment(3)
Nope. Good guess, but uid is not accepted by either docker volume create or docker run --mount.Hypodermis
@Hypodermis did you read the docs, you can't directly pass --uid=nnn you have to pass -o=uid=nnnn and it depends on the storage driver you are using.Slapjack
Yes of course. The former --uid gives (expectedly) an unknown flag error. The latter gives Error response from daemon ... invalid option: "uid". Sorry.Hypodermis
W
0

You can run the following docker command and change the ownership like so:

docker run --rm -v builds:/target alpine:latest sh -c 'chown 1000:1000 /target'

The command will create the "builds" named volume, mount it to a tiny container running as root, and change its ownership to user id 1000.

Now when mounting the named volume on your container, it will be mounted as non-root

Wary answered 2/8, 2023 at 11:13 Comment(0)
A
0

The permissions for a named volume are derived from the permissions for the folder from which it is created. Assuming the default driver is used, you can find the the volume's folder using

$ docker volume inspect mynamedvolume
[
    {
        "CreatedAt": "2000-01-01T00:00:00Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/mynamedvolume/_data",
        "Name": "mynamedvolume",
        "Options": null,
        "Scope": "local"
    }
]

Notice the Mountpoint entry.

You can then change its permissions using the usual methods

chown 1000:1000 /var/lib/docker/volumes/mynamedvolume/_data

When you next mount it, it will have the matching user.

Automatically created named volumes will generally use the local driver, and create the matching mount point as root:root. So, barring any highly unusual changes to the configuration, the above should work.

Allegory answered 29/6 at 13:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.