Docker Security Cheatsheet
Hardening flags, Dockerfile practices, scanning, and a production checklist.
Flag / option
Purpose
--user 1000:1000
Run as non-root UID/GID
--read-only
Read-only root filesystem
--tmpfs /tmp
Writable temp with read-only root
--cap-drop ALL
Drop all Linux capabilities
--cap-add NET_BIND_SERVICE
Add only required caps
--security-opt no-new-privileges
Block privilege escalation
--security-opt seccomp=profile.json
Custom seccomp profile
--memory 512m
Memory limit (DoS mitigation)
--cpus 1.0
CPU limit
FROM node:22-alpine
RUN addgroup -S app && adduser -S app -G app
USER app
COPY --chown=app:app . .
HEALTHCHECK CMD wget -qO- http://localhost:3000/health || exit 1
Pin base images with digest or version tag.
Do not COPY secrets into the image.
Use multi-stage builds to exclude build tools from the final image.
docker scout quickview myimage:tag
docker scout cves myimage:tag
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myimage:tag
Approach
When to use
Environment variables
Non-sensitive config only
Bind-mounted files
Dev/single-host; restrict permissions
Docker Swarm secrets
Swarm deployments
External secret store
Production (Vault, cloud SM)
Security checklist (production images)
Root in container is still powerful — UID 0 inside the container can be dangerous with misconfigured caps.
Socket mount = root on host — Mounting docker.sock into a container grants host-level control.
.env in git — Never commit real passwords; use .env.example templates.
latest tag — Unpredictable updates can introduce vulnerabilities silently.
Scanning is not enough — Fix CVEs by rebuilding with patched bases, not ignoring high severity.