Recently I worked on a project called Pure Service Orchestrator™ Explorer, or in short PSO Explorer. PSO Explorer gives administrators and platform owners visibility in container storage usage. You can read more on this project here. Anyways, many of our customers running production environments are using RedHat OpenShift Container Platform. One of the advantages of OpenShift is security. However for me as a developer of PSO Explorer that caused me some obstacles, as I had to change PSO Explorer to run as a non-root container.
Why do we need non-root containers?
When you create a container and don’t specify the
USER command in the Dockerfile, the container will run as root user. Therefor it is not uncommon for a container to run as root user.
However OpenShift runs every container as a unique user, other than root. The user ID that is used is determined at run time. The idea behind this is that if somehow a hacker could break out of the container, they would not have any permissions on the host system. So from a security perspective it’s a good thing to not run as a root user.
So even if you did not specify the
USER command in the Dockerfile for the container and start the container on OpenShift, it will run as a semi random user. This in turn will probably cause file permissions issues, since this user might not have sufficient access to the files that it needs (eg. /var/log or /etc).
What to change?
Since the UID of the user is not known at build time, using
chown to set the user for the directories and files is no option. Except that the nice thing is, that primary group for the user used, is always
root (of GID 0).
With that in mind, we can change the permissions, using the group membership as so in our Dockerfile:
RUN chown -R 1001:0 /var/log/nginx RUN chmod -R g+w /var/log/nginx
The first command will make group
root (which has id 0) owner of the directory (in this case the log directory for nginx). The second command will add write permissions for the group to the directory.
Now when the container is started, the user has read/write permissions to the directory, even though the UID that is used, does not have these permissions.
Another thing you might run into, is that in Linux a non-root user cannot bind to a TCP port lower than 1024. So if you’re running NGINX for example, as I was, you’ll have to change the port number. In mu case I choose to use port 8080 for the container, instead of the default port 80. I use a Load Balancing service to forward traffic from port 80 to port 8080 on the container.
Finally it’s good practice to add the
USER command to your Dockerfile as well, to make sure that it doesn’t run as root.
Running containers as non-root user, makes complete sense from a security perspective. It reduces the risks if a user was to break out of the container. However since the UID is random on the OpenShift container platform, you’ll need to make sure that you use the primary group (
root or group ID 0) to assign permissions to the container. Also make sure that you change any TCP ports to a value higher than 1024. Otherwise your service or application might not be able to start.