Docker can run commands as the root user if you want, but it also offers a similar flag called Privileged. In the context of containers. however, this is very different from root usage, and it’s important to understand the differences to secure your systems.
What Does “Root” Even Mean?
The difference between a user inside a container and a user outside a container comes down to how Docker works under the hood. The underlying tech behind Docker is Linux namespaces, which achieve isolation at the kernel level.
The core concept is pretty simple. From the host’s perspective, a Docker container might store its data in /var/lib/docker/container/, but because the container is in a separate “Mount” namespace, it’s presented as /, and the container is none the wiser. Multiple namespaces types exist, such as the Process and IPC namespace, Network namespace, and User namespace. Docker makes use of all of them to make containers work.
The Docker daemon runs as root on the host machine, so by default all containers also run as root. The root user inside the container is the same as the root user outside of the container. This isn’t a massive issue usually, because it’s still isolated from the other containers with all the other namespaces. A process running as root in the container won’t be able to access files outside of its jailed directory.
This still leaves it open to theoretical privilege escalation attacks, so many people will choose to remap the container’s root user with the –user flag setting it to run as a less-privileged user on the host machine and denying any kind of root access. Pass it an arbitrary user ID, and Docker will map root (ID 0) inside the container to the user ID specified:
Of course, this root user will still have full access to the container, and general Linux best security practices still apply. You should set up your own users and run your applications like you would on a regular Linux system. This keeps the potential attack surface low, and when combined with user remapping, means the container will have no possibility of easily breaking out.
Privileged Allows Container Escape
Privileged is different. It’s a special flag you can set at runtime specifically to allow a Docker container to break free from its namespaces and access the entire system directly. Generally, this is a very bad idea, as this allows malicious code from the container to do nasty things like overwrite the host’s .ssh/authorized_keys or delete disk partitions.
It also just defeats the purpose of container isolation, but it does have some use cases. Running as privileged is the same as running a process on the host machine, except you do get the organizational benefits of being able to run in a container. If you’re running processes that need to directly access hardware on the machine, like network devices, or need to have read/write access to the root partition, you can run them as privileged to allow for this. Another major use case is Docker in Docker, or DinD, which is used by Jenkins to allow for building Docker containers inside the Jenkins container.
How to Install and Use Jenkins to Build a CI/CD Pipeline
However, for anything else, this is probably unnecessary, and just poses more risks. If you know what you’re doing though, and would like to run a container as privileged, you’ll need to pass in the –privileged flag.
The same functionality is available to Kubernetes, using securityContext: