Process Clients FAQ Team Blog Imprint
Updated on in #devops, #docker — 5 Minute Read

Telling Docker Who You Are

Did you ever notice that if you create files on a Docker bind mount from within a container, they all belong to root on the host system? This behavior can lead to permission problems if, for instance, you depend on Docker to automate parts of your build pipeline.

Let me start with a bit of background information about user management on Linux. Internally, Linux maps user names to user IDs (aka UIDs) and group names to group IDs (aka GIDs). ID 0 is special for both users and groups because it identifies the root user and the root group. This is hard-coded in the kernel and is, therefore, true on all Linux systems - even inside of Docker containers.

With id, it’s straightforward to find the UID/GID of a given user:

1
2
3
4
$ echo "My UID is $(id -u), and my GID is $(id -g)."
My UID is 1000, and my GID is 1000.
$ echo "root's UID is $(id -u root), and root's GID is $(id -g root)."
root's UID is 0, and root's GID is 0.

Similarly, you can use stat to find the owner of files and directories:

1
2
3
$ touch zeroth-experiment
$ stat --format="Owner UID is %u, and owner GID is %g." zeroth-experiment
Owner UID is 1000, and owner GID is 1000.

Alright, that’s all the background information you need to know. Now, let’s create a simple Docker image and run our first experiment:

1
2
3
4
5
6
FROM alpine:3.10.3

WORKDIR /work
VOLUME /work

ENTRYPOINT ["sh", "-c"]
1
2
3
4
5
6
7
8
9
$ echo "My UID is $(id -u), and my GID is $(id -g)."
My UID is 1000, and my GID is 1000.
$ docker build -t bugfactory/permission-test .
# (output removed)
$ docker run --volume $(pwd):/work \
             bugfactory/permission-test \
             "touch first-experiment"
$ stat --format="Owner UID is %u, and owner GID is %g." first-experiment
Owner UID is 0, and owner GID is 0.

Our command successfully created the file first-experiment, but the file belongs to root as indicated by the UID/GID in the output’s last line.

As it turns out, Docker runs commands as root by default. To tell Docker to use a different UID/GID, we can use its --user UID:GID flag. Knowing about --user and id, we can compose an option, such that Docker always runs the command given to it as the user who invoked Docker on the host system: --user $(id -u):$(id -g). Let’s try this:

1
2
3
4
5
6
7
8
$ echo "My UID is $(id -u), and my GID is $(id -g)."
My UID is 1000, and my GID is 1000.
$ docker run --volume $(pwd):/work \
             --user $(id -u):$(id -g) \
             bugfactory/permission-test \
             "touch second-experiment"
$ stat --format="File owner UID is %u, and owner GID is %g." second-experiment
File owner UID is 1000, and owner GID is 1000.

Same as before, the command successfully created the file second-experiment, but this time it belongs to our UID/GID as proven by the output’s last line. Problem solved!


Notes
Software: Alpine v3.10.3, Docker v19.03.

Feedback or Questions?

Let's Talk on Twitter