File Ownership in Docker Volumes
I had a revelation recently about the relationship between containers and mounted volumes. When I set up a Rails environment with Docker, I sometimes work with the root user of the container, but I suspect this is a bad practice. More recently, I’ve begun creating an unprivileged user to serve files in the container, which more closely parallels the setup of a real production environment. I noticed that this user automatically became the owner of files in volumes mounted from my local directories, but I never took the time to dig into a mystery that worked in my favor. The ability to edit files locally and also run generators in the container without doing any other access management is awfully convenient.
However, in programming, mysteries are inherently bad. A desirable surprise can be just as problematic as an undesirable one. If you don’t know why a thing works, you don’t know how to make sure it will continue working. I tried to share a Docker Compose project with a colleague recently, and discovered that the magic was missing. His mounted files belonged to a mysterious “1001” user within the container.
If you understand the Linux filesystem more intimately than I do, you probably see where this is going. I learned two crucial things from a StackOverflow question. First, file ownership is assigned by ID, not by user name. Like URLs, Linux usernames are a label for human convenience. Files can even be owned by a uid for which no user account exists. Second, file ownership in a mounted directory is determined by the same bits locally as it is in the container. If a file belongs to uid 1000 locally, it also belongs to uid 1000 in the mounted volume, even if user 1000 has a different name in the container. I happen to be the only user on the machines I use, and it happens to be the first account created on each, so I’m always 1000. The Rails user is the first and only account I create in my container. It’s always 1000 as well. Total coincidence. My colleague happened to be using the second account on his machine, thus 1001.
Unfortunately, this story doesn’t end with a clean solution. When using a development environment in Docker, I think there’s a strong case to be made for having a user in the container who owns the local user’s files. I would love to see some official support for that idea. In the short run, I’ve resorted to defining an ARG in the Dockerfile to allow for passing flags to the useradd
command. If there are better options, or if I’m just blatantly missing something, I’d love to hear about it.