Imagine the following scenario: your world-famous web application is hosted with two Docker containers (eg. with application server). Both containers have access to same host's directories (passed with Docker's -v parameter) mounted as:

  • /configuration - containing few configuration files,
  • /logs - storing log files outside containers.

Arguably, there are lots of better solutions (including databases, log indexing systems etc.) but that's the issue we need to face now.

The following user accounts are involved:

  • admin - host OS
  • web1 - first container
  • web2 - second container

Problematic scenarios

#1 admin changes configuration file

Result: web1 and web2 may (both, one or none of them) get Permission denied exception.

#2 admin reads logs written by web1 or web2

Result: admin may get Permission denied exception (without sudo).

#3 admin lists logs directory contents
$ whoami
$ ls -la logs
-rw-r--r--   1        1003     1003     0 05-12 11:28 application.log
-rw-r--r--   1        lightdm  network  0 04-04 04:15 yetanother.log
$ # lightdm user? o.O

Scenarios above show typical file permission problems, which are not strictly related to Docker or Linux itself. However, running Docker containers enforces using separate user for each container / app. The situation could be even worse, when instead of any user above its actions will be performed as root.

This should be a geek meme...

Obviously, one can just run all actions in containers as root and use sudo to write/read from the admin account, however:

  • performing all action as root can significantly reduce security,
  • admin user may not have sudo permission.

Solution? One to rule them all!

Let's go back to the root only actions case. root on host system can read & modify files owned by the root inside the container because they both share the same User identifier (UID) value (0 by default)- a number representing a user in Unix-like systems.

$ id -u admin # check admin UID
$ chown admin file.txt # make admin user file owner
$ ls -la | grep file.txt
-rw-r--r--   1 admin users     0 09-11 23:34 file.txt
$ chown 1002 file.txt # same effect as before
$ ls -la | grep file.txt
-rw-r--r--   1 admin users     0 09-11 23:34 file.txt

The reason of strange ls -la output in scenario #3 are different UIDs. Possibly, web1 has UID value 1003 (inside the container) and web2 UID is the same as lightdm user on the host OS.

Simple and straightforward solution to this problem, is to keep the same UID value for all users "collaborating" with each other. Setting UID value 1002 for web1 and web2 users inside their containers, can lead to the following result:

$ whoami
$ ls -la logs
-rw-r--r--   1        admin  admin    0 05-12 11:28 application.log
-rw-r--r--   1        admin  network  0 04-04 04:15 yetanother.log

How to set UID value for given user?

  • during manual user creation pass it as an argument option: useradd -u UID username ...
  • for existing user execute usermod -u UID username

CAUTION! changing existing user's identifier breaks file permissions! (which are still based on old UID value) Additional chown will be required on all owned files!

So, all you gotta do is to add a suitable command to each of your Dockerfile, rebuild images and enjoy another solved task :-)