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

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!

Ready to Learn More Web Development?

Join my Mailing List to receive 1-2 useful Articles per week.

I send up to two weekly emails on building performant and resilient Web Apps with Python, JavaScript and PostgreSQL. No spam. Unscubscribe at any time.

Continue Reading?

Here are a few more Articles for you ...

Why JavaScript’s undefined Isn’t What You Think It Is

In this informative article, you learn that undefined is not a keyword in JavaScript, and it's up to you to ensure it refers to the value its name suggests.

By Christoph Schiessl on JavaScript

Orphaned Branches in Git

Learn about Git's internal data structure and how orphaned branches can be used to create separate histories with their own root commits.

By Christoph Schiessl on DevOps and Git

Portability via Static Linking of libpq

Learn how to remove LDAP support from PostgreSQL packages to remove indirect dependencies, thereby making your programs smaller for Docker images.

By Christoph Schiessl on DevOps, PostgreSQL, and Docker

Christoph Schiessl

Christoph Schiessl

Independent Consultant + Full Stack Developer

If you hire me, you can rely on more than a decade of experience, which I have collected working on web applications for many clients across multiple industries. My involvement usually focuses on hands-on development work using various technologies like Python, JavaScript, PostgreSQL, or whichever technology we determine to be the best tool for the job. Furthermore, you can also depend on me in an advisory capacity to make educated technological choices for your backend and frontend teams. Lastly, I can help you transition to or improve your agile development processes.