Hi,
I do not have a technical problem really, just looking for advice:
I have a host directory which is dedicated for bind mounts (var/foo).
Under that, there is a directory for each user, owned by them and managed by the admins group.
# ls -la /var/foo
drwxr-sr-x 4 my_user admins 4096 Dec 6 17:18 my_user
Each user can freely create directories/files under there which he can mount to their docker container:
# ls -la /var/foo/my_user
drwxrws--- 2 my_user admins 4096 Dec 6 17:18 my_nginx_static_files
But now the issue is, that when they chose to bind mount it to a container (using nginx:latest in this example). The nginx user running the webserver process cannot read the static files mounted (logs + responds with a 403).
So I am in a situation which I don’t really know how to resolve. I understand the host UID/GID permissions are enforced with the bind mounts but that does not help as I am looking for a universal solution and I do not want to check every image to see what UID it uses to give it permissions.
What I am looking for is:
Host system users can only r/w their respective directories (aka the files are not world readable)
Dockerd can read all directories under (var/foo) and I will handle the permissions externally so users can’t mount someone elses directory
I am afraid there is no universal solution, as each image maintainer designs their image in an opinionated way. If a process inside a container does not align with the uid or gid of the directory owner of a bind, it will use whatever permissions the “others” group has for this directory.
You should stick to images that start as a specific user and use the --user {uid of myuser}:{group id of admins} or images that perform user mapping using environment variables. There is no way around studying the image description.
For instance, the maintainer linuxserver creates user-friendly images that allow user mapping using environment variables.
I have tried this on the official nginx image which failed due to an internal file permission error (the provided user could not read the files in the container itself). But it certainly seems like the way to go.
Yeah this is great, I’ll look into those images.
And how should I proceed with custom dockerfiles? I can not ensure that each user will be responsible and might just stick to root for what I know. Then if I run the container as a different user, I will certainly get internal permission errors if the image is built with root as default no?
From what I remember, the official nginx image allows running as unprivileged user, but it requires a custom configuration. It should be described in the image description. It is even possible to use the image with a read-only container file system, if a custom config, and volumes are used.
If you create your own images, you either need to make sure that you declare a USER instruction to make a container based on that image use this user id. Generally, you will want to design your image in a way that it works with an arbitrary user id, so that users can override the userid with the --user argument.
Another approach is to not set the USER instruction, and instead use something like gosu or su-exec in your entry point script to execute the main process with an unprivileged user.
Basically you end up with the both approaches described in the other topic.
Though, if you don’t trust your users, it’s a terrible idea to give them access to the docker.sock on an unhardened docker installation, as no one can stop them from starting containers as root, and mounting any path from the host into their container. They could easily mount /etc/ into a container and add themself to the sudoers or root group.
There are ways to harden your docker installation. It has been discussed a couple of times in the forum. The forum search should help to find those topics.
You could leverage open policy agent to tailor what your users are allowed to request from the docker engine. But it requires the docker engine to expose its api via https, and requires certificate based user authentication + modelling of the open policy agent rules. I am not sure if this works with rootless docker.