I recently created a docker image for an open source project of mine. It supports running the application internally as a non-root user via
PGID environment variables.
I recently got the feedback that this approach has security flaws and that
--user is much preferred. However, without executing the entrypoint script as a root user, I won’t be able to execute certain setup tasks such as
chmod on internal directory mount targets.
As I understand it, there seems to be three modes a container can be run in, as it applies to user permissions:
- Full root user. Container is run without
--user and internally all applications run as UID 0.
- Partial root user. Container is run without
--user (it runs as root) but the application is launched as a non-root user
- No root at all. Container is only run with
--user and nothing is executed with root privileges.
Between #2 and #3, what are the specific security concerns? Why does the container need to ‘bootstrap’ as a non-root user if the application itself already runs as non-root? And in what way does a container need to be attached to the network (assume the issues all boil down to network access to the container) for the difference to be meaningful?
Lastly I’ll say that it appears that rootless docker only came to be (officially) in v20.10 which released around Dec 2020. I imagine a lot of “best practices” or de facto standards have been established from popular container registries like Linuxserver.io that will be difficult to “undo”.
Thanks for any information to help me better understand the problem domain and what motivations I should have to address these issues as well as understand their severity and priority.
linuxserver.io images are perfectly suited for beginners and are aimed for convenience. Most beginners have a hard time to understand that they need to allign the owner the host path of a volume bind with the uid/pid of the process inside the container. Many users do not even care to read the dockerhub description, but instead trust whatever tutorial they find in the internet which wildly differ in quality. Their images are far away for beeing best practive for enterprise grade operation - if I am not mistaken they don’t even work on openshift due to s6-overlay.
If you want best practice, take a look at the official images - you will notice that most of them will start with a restricted user . If you want to create enterprise grade images, take a look at bitnami images - every image I used from them so far was starting as restricted user. Their images are not necessarily beginner friendly, as their objective is secure enterprise operations.
Recently I have seen images like the official pihole image that don’t even start as priviliged container anymore, as they check for capabilities and let the container die in case the expected capabilities are not present or can not be added while starting the container.
Regardless wether you execute the docker commands as a restricted user or root, regardless wether the container starts as a restricted user or root, the docker engine itself is running with root permissions. This is why providing a restricted user access to the docker cli allows easy privilige escallation - nothing is stopping the restricted user to start a container to mount /etc into the container and modify it inside the container with root privilges.
Rootless docker on the other hand is a docker engine that is run as unpriviliged user - it is not activated by default. In rootless docker the root user is actualy not the same root as on the host - it is mapped against an unpriviliged user id.
We can all aggree that starting the container process as unrestricted user is the safest way to operate a container. Though, I would still consider the partial root approach as safe as well, if it’s done correct! I would suggest to tailor your images towards the end user group your expect it to use. I personaly prefer bitnami images over linuxserver.io images, but they are less convinent to use.
Btw, you can find plenty of examples of container escaping in the internet.