Skip to content

Container Security

This chapter covers container security best practices.


Container security is critical - containers share the host kernel and can be a vector for attacks. A single vulnerable container can compromise the entire host and other containers.

┌─────────────────────────────────────────────────────────────────────────────┐
│ CONTAINER SECURITY IN DEVOPS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ SECURITY LAYERS │ │
│ │ │ │
│ │ • Image Security - Scan for vulnerabilities, use minimal images │ │
│ │ • Runtime Security - Run as non-root, limit capabilities │ │
│ │ • Network Security - Network policies, segmentation │ │
│ │ • Secrets Management - Never store secrets in images │ │
│ │ • Pod Security - Security contexts, admission controllers │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ COMMON THREATS │ │
│ │ │ │
│ │ • Image vulnerabilities - Outdated base images with CVEs │ │
│ │ • Privilege escalation - Container breaks out to host │ │
│ │ • Secrets exposure - Credentials in image layers │ │
│ │ • Supply chain attacks - Compromised registries │ │
│ │ • Resource exhaustion - DoS via container │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Container Security Layers
+------------------------------------------------------------------+
| |
| 1. Registry Security |
| - Use trusted images |
| - Scan for vulnerabilities |
| - Sign images |
| |
| 2. Image Security |
| - Minimal base images |
| - No secrets in images |
| - Multi-stage builds |
| |
| 3. Runtime Security |
| - Drop capabilities |
| - Run as non-root |
| - Resource limits |
| - Network isolation |
| |
| 4. Orchestration Security |
| - RBAC |
| - Network policies |
| - Pod security policies |
| |
+------------------------------------------------------------------+

# Use specific tags
FROM nginx:1.24
# Don't run as root
USER nginx
# Use read-only filesystem
# docker run --read-only nginx
# Remove unnecessary packages
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

Terminal window
# Don't run privileged
docker run --privileged nginx # AVOID
# Drop capabilities
docker run --cap-drop=all --cap-add=NET_BIND_SERVICE nginx
# User namespace remapping
# /etc/docker/daemon.json
{
"userns-remap": "default"
}
# seccomp profile
docker run --security-opt seccomp=default.json nginx
# AppArmor profile
docker run --security-opt apparmor=docker-default nginx

Terminal window
# Create secret
echo "password" | docker secret create db_password -
# Use in service
docker service create --secret db_password nginx
# Use secret as env var
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password

Terminal window
# Trivy
trivy image nginx:latest
trivy image --severity HIGH,CRITICAL nginx:latest
# Clair
clair-scanner nginx:latest
# Anchore
anchore-cli image add nginx:latest
anchore-cli image vuln nginx:latest

allow-nginx.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-nginx
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: client
egress:
- to:
- podSelector:
matchLabels:
app: database

pod.yaml
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
# Capabilities
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE

WRONG:

FROM ubuntu
# Runs as root by default
CMD ["/bin/sh"]

CORRECT:

FROM ubuntu
RUN useradd -m appuser
USER appuser
CMD ["/bin/sh"]

Why: Root in container = root on host if container escapes.


WRONG:

Terminal window
# Pull and run any image
docker pull random-user/myapp
docker run random-user/myapp

CORRECT:

Terminal window
# Scan before running
docker scan myapp:latest
trivy image myapp:latest
# Use only signed images
docker trust key generate myapp
docker pull myapp:latest

Why: Unscanned images may have critical vulnerabilities.


WRONG:

FROM node:18
COPY . .
ENV API_KEY=secret123 # Bad!
RUN echo password > /app/secret # Bad!

CORRECT:

FROM node:18
COPY . .
# Use runtime secrets, not build-time
# Docker Swarm: --secret
# Kubernetes: Secrets volume
# Or env vars from outside

Why: Secrets in images persist in layers, accessible to anyone who pulls image.


WRONG:

Terminal window
# Full host access
docker run --privileged myapp
# OR
docker run --cap-add ALL myapp

CORRECT:

Terminal window
# Minimal capabilities
docker run \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--read-only \
myapp

Why: Privileged containers can access all host devices - huge attack surface.


WRONG:

# All pods can talk to all pods
kind: Pod
spec:
containers:
- name: app
image: myapp

CORRECT:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress

Why: Default-allow network is risky; implement zero-trust networking.


In this chapter, you learned:

  • ✅ Container security principles
  • ✅ Image security best practices
  • ✅ Runtime security hardening
  • ✅ Secrets management
  • ✅ Image scanning
  • ✅ Network policies
  • ✅ Pod security standards

In this part, you learned:

  • ✅ KVM/QEMU virtualization
  • ✅ Docker fundamentals
  • ✅ Docker advanced networking/storage
  • ✅ Kubernetes basics
  • ✅ Container security

Chapter 61: HA Concepts and Design


Last Updated: February 2026