principledockerMajor
Always run containers as a non-root user
Viewed 0 times
non-rootUSERsecurityleast privilegerootlessadduseruseradd
Problem
Containers run as root by default. If the application is compromised, the attacker has root access inside the container and may exploit kernel vulnerabilities or escape to the host.
Solution
Create and switch to a non-root user in your Dockerfile:
For Alpine:
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
USER appuserFor Alpine:
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuserWhy
Defense in depth: even if the process is compromised, running as a non-root UID limits what an attacker can do on the host filesystem and reduces the blast radius of a container escape.
Gotchas
- Some base images already define a non-root user (node image provides
nodeuser, nginx providesnginx) - Ports below 1024 require root or CAP_NET_BIND_SERVICE — expose on 8080 instead of 80
- Files COPYed before the USER instruction are owned by root — use COPY --chown
- USER instruction in Dockerfile can be overridden at runtime with
docker run -u root— enforce with Kubernetes securityContext or rootless Docker
Code Snippets
Running Python app as nobody user
FROM python:3.12-slim
WORKDIR /app
# Install deps as root before switching user
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY --chown=nobody:nogroup . .
USER nobody
EXPOSE 8080
CMD ["python", "-m", "gunicorn", "--bind", "0.0.0.0:8080", "app:app"]Context
Any production Docker image
Revisions (0)
No revisions yet.