Deriving FROM existing Dockerfile + setting USER to non-root

10/14/2019

I'm trying to find a generic best practice for how to:

  1. Take an arbitrary (parent) Dockerfile, e.g. one of the official Docker images that run their containerized service as root,
  2. Derive a custom (child) Dockerfile from it (via FROM ...),
  3. Adjust the child in the way that it runs the same service as the parent, but as non-root user.

I've been searching and trying for days now but haven't been able to come up with a satisfying solution.

I'd like to come up with an approach e.g. similar to the following, simply for adjusting the user the original service runs as:

FROM mariadb:10.3

RUN chgrp -R 0 /var/lib/mysql && \
    chmod g=u /var/lib/mysql

USER 1234

However, the issue I'm running into again and again is whenever the parent Dockerfile declares some path as VOLUME (in the example above actually VOLUME /var/lib/mysql), that effectively makes it impossible for the child Dockerfile to adjust file permissions for that specific path. The chgrp & chmod are without effect in that case, so the resulting docker container won't be able to start successfully, due to file access permission issues.

I understand that the VOLUME directive works that way by design and also why it's like that, but to me it seems that it completely prevents a simple solution for the given problem: Taking a Dockerfile and adjusting it in a simple, clean and minimalistic way to run as non-root instead of root.

The background is: I'm trying to run arbitrary Docker images on an Openshift Cluster. Openshift by default prevents running containers as root, which I'd like to keep that way, as it seems quite sane and a step into the right direction, security-wise.

This implies that a solution like gosu, expecting the container to be started as root in order to drop privileges during runtime isn't good enough here. I'd like to have an approach that doesn't require the container to be started as root at all, but only as the specified USER or even with a random UID.

The unsatisfying approaches that I've found until now are:

  • Copy the parent Dockerfile and adjust it in the way necessary (effectively duplicating code)
  • sed/awk through all the service's config files during build time to replace the original VOLUME path with an alternate path, so the chgrp and chmod can work (leaving the original VOLUME path orphaned).

I really don't like these approaches, as they require to really dig into the logic and infrastructure of the parent Dockerfile and how the service itself operates.

So there must be better ways to do this, right? What is it that I'm missing? Help is greatly appreciated.

-- Oliver
docker
dockerfile
kubernetes
openshift

1 Answer

10/14/2019

Permissions on volume mount points don't matter at all, the mount covers up whatever underlying permissions were there to start with. Additionally you can set this kind of thing at the Kubernetes level rather than worrying about the Dockerfile at all. This is usually though a PodSecurityPolicy but you can also set it in the SecurityContext on the pod itself.

-- coderanger
Source: StackOverflow