Eldad Assis
Eldad Assis

Reputation: 11045

Docker custom user id permissions in a volume (mounted and not mounted)

On the lates MacOS, with Docker for Mac Version 18.06.0-ce-mac70 (26399).

I built an example Docker image that runs as non-root with a custom user created. This is the Dockerfile:

FROM debian:jessie

RUN mkdir /data && \
    groupadd bar && useradd -d /home/foo -g bar -m -s /bin/bash foo && \
    chown foo:bar /data

VOLUME /data

USER foo

ENTRYPOINT ["/bin/bash"]

I built the image. Called it test:1

When I run

docker run -it test:1 -c "ls -la /data"

I see /data is properly owned by user foo:bar.

When I run

docker run -it --user 1717:1818 test:1 -c "ls -la /data; touch /data/test"

I get the a permission error

total 8
drwxr-xr-x 2 foo  bar  4096 Aug 18 18:04 .
drwxr-xr-x 1 root root 4096 Aug 18 18:12 ..
touch: cannot touch '/data/test': Permission denied

If I mount a host directory

docker run -it --user 1717:1818 -v $(pwd)/data:/data test:1 -c "touch /data/test; ls -la /data"

It works without an error!

total 4
drwxr-xr-x 3 1717 1818   96 Aug 18 18:18 .
drwxr-xr-x 1 root root 4096 Aug 18 18:20 ..
-rw-r--r-- 1 1717 1818    0 Aug 18 18:20 test

Now I go into the container to debug

docker run -it --user 1717:1818 test:1

And I'm in a shell. Running a few tests:

I have no name!@75deaf12dcdd:/$ id
uid=1717 gid=1818 groups=1818

I have no name!@75deaf12dcdd:/$ cat /etc/passwd
...
foo:x:1000:1000::/home/foo:/bin/bash

So.. finally to my questions.

Upvotes: 4

Views: 10020

Answers (2)

Eldad Assis
Eldad Assis

Reputation: 11045

The current solution I have working uses the following Dockerfile:

FROM debian:jessie

RUN mkdir /data && \
    groupadd bar && useradd -d /home/foo -g bar -m -s /bin/bash foo && \
    chmod 777 /data

VOLUME /data

USER foo

ENTRYPOINT ["/bin/bash"]

All I did was change the permission on /data to 777 (chmod 777 /data instead of chown foo:bar /data) at build time.
This allowed my container to write to to a mounted /data (that was set to be owned by 1717:1818 on the host).

docker run -it --user 1717:1818 test:1 -c "touch /data/test; ls -la /data"

Now works:

total 8
drwxrwxrwx 2 1717 1818 4096 Aug 21 20:15 .
drwxr-xr-x 1 root root 4096 Aug 21 20:21 ..
-rw-r--r-- 1 1717 1818    0 Aug 21 20:21 test

I'll be happy to hear ideas about ideas to get rid of the 777 on /data

I hope this helps.

Upvotes: 1

David Maze
David Maze

Reputation: 158758

A very typical use of an ENTRYPOINT is to have it set to a wrapper script that receives the "real" command as command-line arguments. It does whatever setup it needs to do, then runs the actual command.

#!/bin/sh
chown -R ...
exec "$@"

Then in the same way you can run the base images with just a command line, you can run your own images, without a random -c argument

docker run ubuntu:18.04 ls -l /
docker run test:1 ls -l /

Whatever it is your container usually does, you'd set it as a CMD.

COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
CMD ["my-server", "--foreground"]

If you needed an interactive shell, your entrypoint script gets to do its setup before the actual shell gets launched.

docker run --rm -it test:1 sh

I believe the bind-mounted volume's ownership changing is specifically a feature of Docker for Mac, and it's a consequence of Docker running in a hidden Linux VM that can't directly use the OSX host filesystem. There is some extended discussion in the Docker documentation, more specifically including what happens when a container chowns a file.

Upvotes: 2

Related Questions