Container security is not a product you buy. It’s a set of practices applied across the full container lifecycle — from the Dockerfile to the running pod in production.
This post covers the fundamentals I wish someone had explained to me clearly when I first stepped into the security role.
The Container Attack Surface#
A container is not a VM. The kernel is shared between the host and all containers on that node. That single fact changes everything about how you think about isolation.
The attack surface has four main layers:
- The image – What’s baked into the container at build time (CVEs, hardcoded secrets, unnecessary packages)
- The runtime – What the container is allowed to do when it runs (capabilities, syscalls, namespace escapes)
- The orchestration layer – What Kubernetes permits (RBAC, network policies, admission controllers)
- The supply chain – Where the image came from, whether it was tampered with
Each layer needs its own controls. Scanning images alone is not container security.
The Most Important Controls#
1. Run as non-root#
This is the single most impactful change you can make with minimal effort:
securityContext:
runAsNonRoot: true
runAsUser: 65534Most real-world container escapes require the process to be running as root (UID 0) inside the container. Don’t run as root.
2. Drop capabilities#
Linux capabilities are the fine-grained permission system below root. Most workloads need none of them:
securityContext:
capabilities:
drop:
- ALLAdd back only what you actually need (e.g., NET_BIND_SERVICE for binding to ports < 1024).
3. Use read-only root filesystem#
If an attacker gains code execution, a read-only filesystem prevents them from dropping payloads:
securityContext:
readOnlyRootFilesystem: trueMount writable emptyDir volumes only for the paths that genuinely need writes.
4. Scan images, enforce a policy#
Trivy is the de facto standard for image scanning. But scanning alone means nothing without enforcement. Use an admission controller (OPA Gatekeeper or Kyverno) to block pods that exceed your severity threshold:
trivy image --exit-code 1 --severity CRITICAL myimage:latest5. Sign and verify images#
Use Cosign (part of Sigstore) to sign every image in CI and verify signatures before deployment. This is your defense against supply chain attacks:
cosign sign --key cosign.key myregistry/myimage:v1.0.0
cosign verify --key cosign.pub myregistry/myimage:v1.0.0Where to Start#
If you’re new to container security and need to prioritize:
- Enforce
runAsNonRootandreadOnlyRootFilesystemvia a Kyverno/OPA policy cluster-wide - Add Trivy to your CI pipeline
- Review your RBAC – most clusters are over-privileged
- Enable audit logging and understand what’s happening in your cluster
Security is iterative. Don’t wait for the perfect setup before starting.
This is the first post in a series on container security fundamentals. Next up: image scanning in depth with Trivy and SBOM generation.