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.0IaC and Terraform Misconfigurations
Container workloads are not deployed in isolation; they run on networks, nodes, and clusters provisioned by infrastructure-as-code. A Terraform misconfiguration — an open S3 bucket, a security group allowing 0.0.0.0/0, or an unencrypted EBS volume — can expose the containers running on top of it. The same shift-left discipline applies: review terraform plan output in the PR before apply, and scan HCL with tools such as Trivy, Checkov, or tfsec. The 2017 Atlantis demo shows the foundational pattern of posting Terraform plans as PR comments and requiring approvals before apply, which is a manual but effective control when automated scanners are not yet in place. Source: Atlantis Walkthrough
Pipeline 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 — the anchor discipline of Runtime Security:
- 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
- A workload reading sensitive host files such as
/dev/memSource: Falco for Kubernetes Security — CKS Scenarios
Falco hooks the syscall stream with an eBPF probe, evaluates events against declarative YAML rules, and emits alerts identifying the exact container.id and k8s.pod.name — deployable either as a cluster DaemonSet or directly on the host.
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
- Terraform — Infrastructure-as-code that provisions the networks and nodes underneath containers
- Atlantis — PR-driven Terraform plan/apply workflow
- Atlantis Walkthrough — Source: Terraform collaboration through GitHub PRs
- SAST, DAST, and SCA — Vulnerability scanning taxonomy
- Kyverno — YAML-driven admission control for the Deploy layer
- Falco — syscall-level runtime threat detection for the Detect layer
- Runtime Security — detecting threats while workloads execute
- Kubernetes Admission Controllers — The PodSecurity controller’s enforcement mechanism
- Enforce Kubernetes Security with Kyverno — Admission-control governance demo
- 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