Skip to content
Back to Deployment

Docker Security

Best practices for secure containers — non-root, minimal base, scanning, signing.

ContainersAdvanced

Why

Container security reduces attack surface: non-root user, minimal base image, vulnerability scanning, and image signing (cosign) prevent tampering and exploits. Docker is used by 59% of professional developers per the Stack Overflow 2024 survey, and Kubernetes runs 60% of containerized workloads in production (CNCF 2024 survey).

Container orchestration reduces deployment-related incidents by 35% through declarative rollouts.

When

Apply to all production containers — security is not optional. Skip containers for simple static sites — a CDN + static export is cheaper and faster.

Avoid Kubernetes for teams under 10 people; the operational overhead is not justified.

How

1. Non-root — USER 1000 in Dockerfile 2. Minimal — distroless or alpine base 3. Scan — trivy, grype, or docker scout 4. Sign — cosign for Sigstore signing 5. Read-only — read_only: true in compose 6. No capabilities — cap_drop: [ALL] 7. Secrets — Docker secrets or external

Example

# Dockerfile — secure FROM node:20-alpine RUN addgroup -S app && adduser -S app -G app WORKDIR /app COPY --chown=app:app . . USER app # non-root CMD ["node", "server.js"] # docker-compose.yml — hardening services: app: image: myapp:latest user: "1000:1000" read_only: true cap_drop: [ALL] security_opt: [no-new-privileges:true] tmpfs: [/tmp] # Scan trivy image myapp:latest # Sign with cosign cosign sign --key cosign.key myapp:latest cosign verify --key cosign.pub myapp:latest

Common Problems

  • ⚠Container runs as root — default, add USER directive for non-root
  • ⚠Vulnerable base image — scan regularly, update base on CVEs
  • ⚠Configuration drift between environments — use infrastructure-as-code (Terraform/Pulumi) to keep dev/staging/prod identical

Best Practices

  • ✓Run as non-root user — USER 1000, eliminates most privilege escalation
  • ✓Use distroless base — no shell, no package manager, minimal attack surface
  • ✓Set up health checks and graceful shutdown — handle SIGTERM to drain in-flight requests before exit

FAQ