Telling Docker Who You Are
by Christoph Schiessl on DevOps and Docker
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 some 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 users and groups because it identifies the root
user and the root
group. This is hard-coded in the kernel and is true on all Linux systems - even inside Docker containers.
With id
, it's straightforward to find the UID/GID of a given user:
$ 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:
$ touch first-experiment
$ stat --format="Owner UID is %u, and owner GID is %g." first-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:
FROM alpine:latest
WORKDIR /work
VOLUME /work
ENTRYPOINT ["sh", "-c"]
$ 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 second-experiment"
$ stat --format="Owner UID is %u, and owner GID is %g." second-experiment
Owner UID is 0, and owner GID is 0.
Our command successfully created the file second-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. On the man page for docker run
, this is documented as follows:
-u, --user=""
Sets the username or UID used and optionally the groupname or GID for the specified command.
Knowing about --user
and id
, we can compose an option such that Docker always runs commands as the user who invoked docker run
on the host system: --user $(id -u):$(id -g)
. Let's try this:
$ 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 third-experiment"
$ stat --format="File owner UID is %u, and owner GID is %g." third-experiment
File owner UID is 1000, and owner GID is 1000.
As before, the command successfully created the file third-experiment
, but this time, it belongs to our UID/GID, as proven by the output's last line. Problem solved!