Kryten
Kryten

Reputation: 15780

How do you manage permissions when developing in a Docker container?

When developing in a Docker container on Linux, there is a problem with permissions: how to manage file ownership and permissions between the host and the container.

Imagine that I have a Docker image that runs Ubuntu and an Apache server. Using the default settings for (recent versions of) Apache, the document root will be /var/www/html and Apache will be run as the www-data user.

In order to do some development, I expose the document root via Docker with -v /path/to/my/files:/var/www/html. And this is where the problem arises:

The files in /path/to/my/files are owned by the containers www-data user. If I'm lucky and my host has a www-data user, it will be that user; otherwise, it will be a distinct user local to the container. The permissions on those files will (probably) be 0755.

So, when I'm working away as myself (a user called jsmith), those files cannot be edited by me because of incorrect file permissions & ownership.

The end result is that it is necessary to constantly adjust ownership & permissions on the development files. Other people must have this problem, but every post I've seen on the topic of using Docker in a development workflow just kind of overlooks this problem.

I do have a solution, but I'm not entirely happy with it:

This works well, but seems overly complicated. How do other people solve this problem?

Upvotes: 10

Views: 2568

Answers (2)

BMitch
BMitch

Reputation: 264821

I can think of two solutions:

Use a common group id among all developers and images. The uid may end up being numeric in the container, but the gid would give at least read access, and optionally write access, without giving it out globally. Use the setgid bit on the containing directories to have files automatically created with this gid. This isn't the cleanest approach, and may lead to giving out access to other group members, but it may be much easier to manage depending on your organization's workflow.

The second option is named volumes, which I believe were added after you asked this question. They let you have the data exist with the uid/gid's known to the containers. This has the downside of moving the data into the internal docker directories where it's less easy to manage outside of a container. However, there are microservices approaches that keep the volume synchronized with an outside source (git pull, rsync, etc) using a dedicated container that mounts the same volume. You essentially move all of the reads and writes of the data into containers, including any backups, update routines, and testing scripts.


Update: A third option I often use for development environments is a run an entrypoint script as root that compares the mounted volume uid/gid to the uid/gid of a user inside the container. If they do not match, the uid/gid of the user inside the container is updated to match the host. This allows developers to reuse the same image across multiple hosts where the uid/gid of each developer may be different on their location machine. The code to do this is included in my bin/fix-perms script that is part of my example base image. The last step of my entrypoint script is to then use gosu to drop from root back to the user, now with the changed uid/gid, and all files written will now match those of the user on the host.

If you happen to be running on MacOS, a recent feature called osxfs automatically corrects for uid/gid mismatches with host volumes.

Upvotes: 0

schoel
schoel

Reputation: 863

I realize I'm very likely too late but this might be of help to someone.

In your Dockerfile, you could do this:

RUN usermod -u 1000 www-data
RUN groupmod -g 1000 www-data

This may work in some setups.

Upvotes: 1

Related Questions