Docker Security: Distroless to Runtime
Harden your container supply chain with multi-stage builds, image scanning, runtime policies, and zero-trust networking.
The Container Supply Chain
Container security starts at the base image. Using ubuntu:latest or node:18 pulls thousands of packages you don't need — and each package is an attack surface. Distroless images from Google contain only your application and its runtime dependencies.
Multi-stage builds are your first line of defense. Build in a full-featured image, then copy only the binary and required files to a minimal runtime image.


Image Scanning and Policies
Integrate Trivy or Grype into your CI pipeline to scan images for CVEs on every build. Set a policy: block deployments with Critical or High CVEs, and track Medium CVEs with a remediation SLA.
Pin base image digests (not tags) in production Dockerfiles. Tags are mutable — node:18-alpine might point to a different image tomorrow. Use node:18-alpine@sha256:abc123... for reproducibility.
| Severity | Action | SLA | Gate |
|---|---|---|---|
| Critical | Block deploy | Immediate | 🚫 Pipeline blocked |
| High | Block deploy | 24 hours | 🚫 Pipeline blocked |
| Medium | Track ticket | 7 days | ⚠️ Warning only |
| Low | Backlog | 30 days | ✅ Pass |
Runtime Security
Run containers as non-root with USER 1000:1000. Drop all capabilities with --cap-drop=ALL and add back only what's needed. Mount the filesystem read-only with readOnlyRootFilesystem: true.
In Kubernetes, use Pod Security Standards (restricted profile) to enforce these policies cluster-wide. Combine with Falco for runtime anomaly detection.
# Multi-stage distroless build FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --production COPY . . RUN npm run build FROM gcr.io/distroless/nodejs18-debian12 COPY --from=builder /app/dist /app COPY --from=builder /app/node_modules /app/node_modules USER 1000:1000 CMD ["/app/server.js"]