Running as Non-root

Use the USER instruction so your app runs without root privileges, limiting the damage if the container is compromised.

SyntaxUSER appuser

By default, processes inside a container run as root. If an attacker breaks out of the app, root inside the container is a dangerous starting point. Running as a non-root user is a key hardening step.

The USER instruction

Add a USER instruction in your Dockerfile to switch to an unprivileged user for the rest of the build and at runtime. Many official images already include a suitable user (for example, node).

Creating a user

If no suitable user exists, create one with adduser and make sure it owns the files it needs.

Example

Example · dockerfile
FROM python:3.12-slim

# Create an unprivileged user
RUN useradd --create-home --uid 10001 appuser

WORKDIR /app
COPY --chown=appuser:appuser . .
RUN pip install --no-cache-dir -r requirements.txt

# Drop root before running the app
USER appuser
CMD ["python", "main.py"]

When to use it

  • A security team requires all containers to run as a non-root user so that a container escape does not immediately grant root on the host.
  • A compliance audit flags containers running as UID 0; the team fixes this by adding a USER instruction to every Dockerfile.
  • An Nginx container is configured to run as a non-privileged user by switching to a rootless Nginx image on port 8080.

More examples

Create and switch to a non-root user

Uses the pre-created 'node' user that the node:alpine image includes, and chown-copies files so the user can read them.

Example · dockerfile
FROM node:20-alpine
WORKDIR /app
COPY --chown=node:node package*.json ./
RUN npm ci --omit=dev
COPY --chown=node:node . .
# Switch to the built-in 'node' user
USER node
CMD ["node", "index.js"]

Create a dedicated app user

Creates a dedicated non-root user and group, copies files with correct ownership, then switches before CMD.

Example · dockerfile
FROM python:3.12-slim
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
WORKDIR /app
COPY --chown=appuser:appgroup . .
RUN pip install --no-cache-dir -r requirements.txt
USER appuser
CMD ["python", "app.py"]

Verify container runs as non-root

Confirms the container process is running as a non-root user by printing the effective user identity.

Example · bash
docker run --rm myapp whoami
# Should print: node (or appuser), not root

# Check numeric UID
docker run --rm myapp id

Discussion

  • Be the first to comment on this lesson.