Docker cookbook · Intermediate
Run containers as non-root with a read-only filesystem
Reduce what a compromised container can do without breaking the app.
Approach
Create a user in the image and switch to it. At run time make the root filesystem read-only, provide writable temporary space with tmpfs, drop all capabilities and block privilege escalation.
Solution
FROM python:3.14-slim
RUN useradd --uid 10001 --create-home app
WORKDIR /home/app
COPY --chown=10001:10001 app/ ./app/
USER 10001
CMD ["python", "-m", "app"]
services:
app:
build: .
read_only: true
tmpfs: [/tmp]
cap_drop: [ALL]
security_opt: [no-new-privileges:true]
Pitfalls
- Files copied as root and unwritable for the app user; use
COPY --chown. - Apps that write caches into their install directory fail with a read-only root; point caches at
/tmp. - Binding to ports below 1024 as non-root; use a high port.
Variations
- Rootless Docker or user namespace remapping for host-level protection.
- The same settings in Kubernetes via
securityContext(see the Kubernetes cookbook).
Further reading: Docker Engine security
Reference: https://docs.docker.com/engine/security/
More Docker recipes
- Add a healthcheck to an HTTP service
- Build a layered image for a Spring Boot app
- Build a production image for a Node.js service
- Build a production image for a Python web app
- Build, cache and push images in GitHub Actions
- Build one image tag for amd64 and arm64
- Configure nginx from environment variables
- Develop with Compose and live reload