Docker shared storage file permission problems
Case
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 OSweb1
- first containerweb2
- 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
admin
$ 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
.
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 havesudo
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
1002
$ 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
admin
$ 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 :-)