one common misconception is that containers provide a secure and isolated environment and therefore it’s fine for processes to run as root (this is the default). I mean, it’s not like it can affect the host system right? Turns out it can and it’s called “container breakout”!
with containers, you should also apply the principle of least privilege and run processes as a non-root users. This significantly reduces the attack surface because any vulnerability in the container runtime that happens to expose host resources to the container will be less likely to be taken advantage of by a container process that does not have root permissions.
here’s a rough skeleton of how you can do this by using the USER
directive in the Dockerfile:
# Create a non-root user named "appuser" with UID 1200
RUN adduser --disabled-password --uid 1200 content
# Set the working directory
WORKDIR /app
# Grant ownership and permissions to the non-root user for the working directory
RUN chown -R appuser /app
# Switch to the non-root user before CMD instruction
USER appuser
# ... install app dependencies ...
# this may involve copying over files and compiling
# Execute script
CMD ["./run"]
one thing worth mentioning in this example is permissions.
we use the USER
instruction early on right after we change the ownership of the working directory. since this is happening before we enter the application building phases, it’s possible that the permissions of the user appuser
is insufficient for subsequent commands. For example, maybe at some point in your docker file you need to change the permission of a file that appuser
doesn’t own or maybe it needs to write to a bind-mounted directory owned by a host user. If this applies to your situation, you can either adjust permissions as needed prior to running USER
or move USER
farther down towards the CMD
instruction.
generally speaking, it’s also good practice to ensure that the files that are copied over from the host have their ownership changed to appuser
. this isn’t as critical as ensuring that the process itself is running as non-root via USER
since if an attacker gains privileged access, they can access any file in the container regardless of ownership. nonetheless it’s a good practice that follows the principle of least privilege in that it scopes the ownership of the files to the users and groups that actually need it.
other resources if you’re interested in learning more about this topic:
- https://medium.com/jobteaser-dev-team/docker-user-best-practices-a8d2ca5205f4
- https://www.redhat.com/en/blog/secure-your-containers-one-weird-trick
- https://www.redhat.com/en/blog/understanding-root-inside-and-outside-container