Docker Security: 15 Critical Production Controls
Docker ships with insecure defaults for production. Container escape, privileged mode and public registry images are real attack vectors. Here are 15 controls to harden your container platform.
Image Security (1-5)
1) Use official base images (prefer alpine-like minimal variants over docker.io/library/node). 2) Scan images with Trivy or Grype at every build. 3) Sign images (Cosign) and verify before deploy. 4) Pin image tags (`node:20.11.1-alpine3.19` not `node:20`).
5) Use multi-stage builds — build deps stay out of the final image. A typical Node.js image drops from 1GB to 200MB, attack surface shrinks in proportion.
Runtime Protection (6-10)
6) Don't run as root — USER 1000:1000 in Dockerfile or `--user` on docker run. 7) `--read-only` filesystem (specific tmpfs mounts where writes are needed). 8) `--cap-drop=ALL` and add individual caps only if required (usually none).
9) `--security-opt=no-new-privileges`. 10) Never use `--privileged`. Services that 'need' it are architecturally broken.
Secret Management (11-12)
11) Don't bake secrets into images — ENV or COPY in Dockerfile leaves them in layers, like git history. Use Docker Secrets, HashiCorp Vault, AWS Secrets Manager or K8s Secrets with at-rest encryption.
12) For build-time secrets (private repo SSH keys) use Docker BuildKit's `--secret`. At runtime, prefer mounted files over environment variables — `/proc/<pid>/environ` leaks env vars.
Network Isolation (13-14)
13) Don't use the default Docker network. Create per-app networks; only connect services that must communicate. Inter-microservice segmentation is critical.
14) Minimize inbound ports. Replace `-p 3000:3000` with a reverse proxy (nginx, Traefik). Only the proxy needs outside connectivity; services stay on internal networks.
Monitoring and Audit (15)
15) Watch container behavior — Falco (open-source runtime security), Sysdig, Aqua. Alert on abnormal syscalls (e.g., a container reading /etc/shadow). Pipe Docker daemon logs to ELK.
Containers are ephemeral, so ship logs externally. Centralize with Fluentd, Vector or Filebeat. On Kubernetes, use a sidecar to pull logs from each pod.
Additional Kubernetes Controls
Apply Pod Security Standards (PSS) — 'baseline' as a minimum, 'restricted' as the goal. Use Network Policy to allowlist pod-to-pod traffic. Set up policy-as-code with OPA Gatekeeper or Kyverno (e.g., 'no privileged pods', 'no :latest tags').
Use ImagePolicyWebhook to enforce signed images. Encrypt secrets with a KMS (etcd at-rest encryption). Configure service accounts with least privilege.
Talk to VefaSec about your project or audit needs.
Our Diyarbakır-based team delivers end-to-end software development, penetration testing and cybersecurity advisory to enterprise clients. The discovery call is free and non-binding.