Container Security
Container security is the practice of protecting containerized applications throughout their lifecycle: from secure image construction, through registry scanning, to hardened runtime deployment on Kubernetes. It is a foundational pillar of modern DevSecOps. Source: DevOps to DevSecOps in 9 Hours
The Container Attack Surface
Containers are not inherently secure. They share the host kernel, and a compromised container with excessive privileges can escape to the host. The attack surface spans:
- Base images: Outdated OS packages with known CVEs
- Application layers: Vulnerable language dependencies (npm, pip, Maven)
- Runtime configuration: Root users, writable root filesystems, excessive capabilities
- Orchestration: Misconfigured RBAC, overly permissive NetworkPolicies, exposed registries
Image Construction Hardening
1. Minimal Base Images
Choose the smallest viable base to reduce CVE exposure:
| Base | Size | Use Case |
|---|---|---|
scratch | ~0 MB | Go, Rust static binaries; zero OS attack surface |
distroless | ~15 MB | Language-specific minimal runtime (Java, Python, Node.js) |
alpine | ~5 MB | General-purpose; uses musl libc; smaller but may have edge-case compatibility issues |
debian:slim | ~50 MB | When full glibc compatibility is required |
ubuntu | ~80 MB | Only when specific Ubuntu-only tooling is needed |
The Dockerize a Project page covers Dockerfile best practices including multi-stage builds that copy only runtime artifacts into the final image.
2. Non-Root Execution
Run containers as unprivileged users:
RUN addgroup -g 1001 appgroup && adduser -u 1001 -S appuser -G appgroup
USER appuserIn Kubernetes, enforce this with securityContext:
securityContext:
runAsNonRoot: true
runAsUser: 1001
fsGroup: 10013. Read-Only Root Filesystem
Prevent runtime tampering:
securityContext:
readOnlyRootFilesystem: trueMount an emptyDir volume for any directories that need temporary write access (e.g., /tmp, /var/cache).
4. Drop Capabilities
Remove unnecessary Linux capabilities from the container runtime:
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE # Only if binding to ports < 1024Image Scanning
Image scanning is the process of analyzing a container image for known vulnerabilities in OS packages and application dependencies. It is the primary shift-left control for containers.
Trivy
DevOps to DevSecOps in 9 Hours uses Trivy (by Aqua Security) as the demonstration scanner. Trivy supports:
- OS packages: Alpine, Debian, Ubuntu, RHEL, Amazon Linux
- Application dependencies: npm, pip, Maven, Go modules
- IaC misconfigurations: Terraform, CloudFormation, Kubernetes manifests
- Container registries: Scan images directly from Docker Hub, ECR, GCR, ACR
# Scan a local image
trivy image myapp:1.0
# Scan and fail on critical vulnerabilities
trivy image --severity CRITICAL --exit-code 1 myapp:1.0
# Generate SARIF for GitHub Advanced Security
trivy image --format sarif --output trivy-results.sarif myapp:1.0Pipeline Integration
A typical GitHub Actions step:
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload scan results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'Kubernetes Runtime Security
Pod Security Standards
Kubernetes 1.25+ replaced PodSecurityPolicies with Pod Security Standards (PSS), enforced via the built-in PodSecurity admission controller. Three levels exist:
| Level | Description |
|---|---|
| Privileged | Unrestricted; intentionally dangerous. For system infrastructure only. |
| Baseline | Minimally restrictive; prevents known privilege escalations. Default for most workloads. |
| Restricted | Heavily restricted; follows Pod hardening best practices. For security-critical workloads. |
Enforce at the Namespace level:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restrictedNetwork Segmentation
NetworkPolicies enforce zero-trust east-west traffic. A database should only accept connections from its backend tier, not from the frontend or any arbitrary Pod.
Runtime Threat Detection
Tools like Falco monitor syscalls and Kubernetes audit logs for anomalous behavior:
- A container spawning an unexpected shell (
bash,sh) - A Pod making an outbound connection to a rare IP
- A privileged container being created in a production namespace
The Defense-in-Depth Stack
| Layer | Control | Tool / Pattern |
|---|---|---|
| Image | Minimal base, non-root, read-only FS | Dockerfile best practices |
| Registry | Vulnerability scan before push | Trivy, Snyk Container |
| Build | Fail on critical CVEs | CI/CD quality gates |
| Deploy | Signed images, admission control | Cosign, Kyverno, OPA Gatekeeper |
| Runtime | Network segmentation, resource limits | NetworkPolicies, LimitRanges |
| Detect | Anomaly detection, audit logging | Falco, Prometheus + Alertmanager |
See Also
- Docker Fundamentals — Container primitives prerequisite for security hardening
- Dockerize a Project — Dockerfile construction including non-root and multi-stage patterns
- Kubernetes Network Policies — Runtime network segmentation
- Kubernetes RBAC — Least-privilege orchestration access
- DevSecOps Fundamentals — Container security as a pipeline stage
- Shift Left Security — Image scanning as an early SDLC control
- SAST, DAST, and SCA — Vulnerability scanning taxonomy
- DevOps to DevSecOps in 9 Hours — Day 4: Docker security and Day 5: Kubernetes security demonstrations
Tags: container-security docker kubernetes trivy devsecops pod-security image-scanning