Why non-root containers are important for security

Raquel Campuzano Godoy

As you probably already know, Docker containers typically run with root privileges by default. This allows for unrestricted container management, which means you can do things like install system packages, edit config files, bind privileged ports, etc. This is really useful for development purposes, but can expose you to high risk once you put your containers into a production environment.

Why? Because anyone who accesses your container running as root can start undesirable processes in it, such as injecting malicious code. And running a process in your container as root makes it possible to change the user id (UID) or group id (GID) when starting the container, which makes your application vulnerable.

Changing the configuration of your containers to make them run as non-root adds an extra layer of security. Doing so limits the processes that can be executed and who can execute them. In our quest to continually deliver the latest, most up-to-date and secure applications, Bitnami produces and maintains a selection of non-root image containers - you can find them in our GitHub repository, tagged as "non-root".

In this blog post, I will discuss root and non-root containers in more detail, exploring the difference between the two and the benefits and disadvantages of each. I will also show you an example of how Bitnami creates non-root containers by editing its Dockerfile to change its user permissions and environment variables.

Differences between root and non-root containers

As is explained in the Docker security documentation, running containers and applications with Docker involves running the Docker daemon, and this requires root privileges. Docker needs to have enough permissions to modify the host filesystem to run; otherwise, your container won't be initialized.

But containers don't need to be run as root user. Moreover, applications, databases, load balancers, etc. shouldn't ever be run as root.

Why not provide your containers with security from the beginning, by running them as non-root user?

Following the Principle of Least Privilege (PoLP), the main difference between root and non-root containers is that the latter are focused on ensuring the minimum amount of privileges necessary to run a process.

In this sense, root containers offer the following capabilities:

To modify the container system, allowing the user to do things like edit the host filesystem, install system packages at runtime, etc.

Allow containers to bind ports under 1024.

Meanwhile, non-root containers regulate which users in which namespaces are able to execute specific processes, what volumes can be accessed, and what ports your container is allowed to access.

Advantages of non-root containers

Security

The most important advantage to running your containers as non-root is to ensure that your application environment is secure. To put this in perspective, ask yourself this:

"Would I run any process or application as root in my server?" The answer, of course, would be no, right? So why would you do so in your containers?

Running your containers as non-root prevents malicious code from gaining permissions in the container host and means that not just anyone who has pulled your container from the Docker Hub can gain access to everything on your server, for example. If your container gives users privileges, then anyone could run undesired processes, change the UIDs, or gain access to secrets, etc. You will also probably want to work with non-root containers in a multi-tenant Kubernetes cluster for enforcing security.

While security is the foremost advantage of non-root containers, there are others.

Avoid platform restrictions

Some Kubernetes distributions, such as Openshift, don't allow you to run containers as root. In the case of Openshift, for example, it runs containers with random UIDs which are not compatible with root containers.

Root-only containers simply do not run in that distro. So running non-root containers enables you to use Kubernetes distributions like Openshift. For more information on this, check out the following post about Running Non-Root Containers on Openshift

How Bitnami does create non-root containers?

Bitnami maintains a catalog of more than 80 containers. Some of the infrastructure containers have been released as non-root.

These are some of the Docker containers that Bitnami has released as non-root:

The image above shows three lines highlighted; I am going to explain the meaning and behavior of each:

The BITNAMI_PKG_CHMOD env var defines the file permissions for the folders: write, read or execute.

The ../libcomponen.sh && component_unpack "redis" script is used for unpacking the Redis files and changing the permissions as stated in the BITNAMI_PKG_CHMOD env var.

At this point, everything has been executed as root user at build time of the container. But the last highlighted line indicates that the default user must be changed from root to 1001:

USER 1001: this is a non-root user UID, and here it is assigned to the image in order to run the current container as an unprivileged user. By doing so, the added security and other restrictions mentioned above are applied to the container.

Basically, it has been introduced an environment variable to set the file permissions and specify a user, in order to avoid running the container as root in its Dockerfile. That way, any time you run the container, it will already have the "instructions" to run as non-root user.

This is only one of the many ways to secure your containers. I encourage you to research other ways to turn your Docker images into non-root containers, or to take advantage of the ready-to-run non-root containers already available from Bitnami.

Useful resources

If you want to learn more about non-root containers and Docker and Kubernetes security, check out the following articles: