Container & Kubernetes Security

Container Security Fundamentals

4 min read

Containers revolutionized deployment but introduced new security challenges. Understanding container isolation, image security, and runtime protection is essential for cloud-native security.

Container Threat Landscape

Common Attack Vectors

Attack Vector Description Impact
Vulnerable base images Outdated packages with known CVEs Container compromise
Secrets in images Hardcoded credentials in layers Credential exposure
Privileged containers Running as root with host access Host escape
Insecure registries Pulling from untrusted sources Supply chain attack
Runtime exploitation Memory exploits, code injection Container breakout

Container Isolation Model

┌────────────────────────────────────────────────┐
│                  Host OS Kernel                 │
├────────────────────────────────────────────────┤
│  Container 1    │  Container 2    │  Container 3│
│  ┌──────────┐   │  ┌──────────┐   │  ┌────────┐│
│  │ App      │   │  │ App      │   │  │ App    ││
│  │ Libs     │   │  │ Libs     │   │  │ Libs   ││
│  └──────────┘   │  └──────────┘   │  └────────┘│
│  Namespace      │  Namespace      │  Namespace │
│  cgroups        │  cgroups        │  cgroups   │
└────────────────────────────────────────────────┘

Containers share the host kernel—isolation depends on:

  • Namespaces: Process, network, mount, user isolation
  • cgroups: Resource limits (CPU, memory)
  • seccomp: System call filtering
  • AppArmor/SELinux: Mandatory access control

Secure Docker Configuration

Dockerfile Best Practices

# Use minimal base image with specific version
FROM python:3.12-slim-bookworm AS builder

# Create non-root user
RUN groupadd -r appuser && useradd -r -g appuser appuser

# Set working directory
WORKDIR /app

# Copy requirements first (better caching)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Production stage
FROM python:3.12-slim-bookworm

# Copy only necessary files from builder
COPY --from=builder /usr/local /usr/local
COPY --chown=appuser:appuser . /app

# Never run as root
USER appuser

# Use ENTRYPOINT for immutable commands
ENTRYPOINT ["python", "app.py"]

Key principles:

  • Multi-stage builds to reduce image size
  • Specific version tags (never latest)
  • Non-root user execution
  • Minimal base images (alpine, distroless, slim)

Docker Daemon Security

# /etc/docker/daemon.json
{
  "userns-remap": "default",
  "no-new-privileges": true,
  "seccomp-profile": "/etc/docker/seccomp/default.json",
  "icc": false,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "live-restore": true
}
Setting Purpose
userns-remap Maps container root to unprivileged host user
no-new-privileges Prevents privilege escalation
icc: false Disables inter-container communication
seccomp-profile Restricts system calls

Image Security

Vulnerability Scanning

Trivy - Industry standard scanner:

# Scan local image
trivy image myapp:latest

# Scan with severity filter
trivy image --severity HIGH,CRITICAL myapp:latest

# Scan and fail CI pipeline if vulnerabilities found
trivy image --exit-code 1 --severity CRITICAL myapp:latest

# Scan filesystem (for IaC misconfigurations)
trivy fs --security-checks vuln,config .

Cloud-native scanning:

# AWS ECR scanning
aws ecr start-image-scan \
    --repository-name myapp \
    --image-id imageTag=latest

# GCP Artifact Registry
gcloud artifacts docker images scan \
    gcr.io/project/myapp:latest

# Azure Container Registry
az acr repository show-manifests \
    --name myregistry \
    --repository myapp \
    --query "[].{tag:tags[0],vulnerabilities:changeableAttributes.vulnerabilityAssessment}"

Image Signing and Verification

Cosign for signing container images:

# Generate key pair
cosign generate-key-pair

# Sign image
cosign sign --key cosign.key myregistry/myapp:latest

# Verify signature before deployment
cosign verify --key cosign.pub myregistry/myapp:latest

Runtime Security

Container Runtime Best Practices

# Run container with security options
docker run \
    --read-only \
    --no-new-privileges \
    --cap-drop ALL \
    --cap-add NET_BIND_SERVICE \
    --security-opt="no-new-privileges:true" \
    --pids-limit 100 \
    --memory="512m" \
    --cpus="0.5" \
    myapp:latest
Flag Security Benefit
--read-only Prevents filesystem writes
--cap-drop ALL Removes all Linux capabilities
--cap-add Adds only required capabilities
--no-new-privileges Blocks privilege escalation
--pids-limit Prevents fork bombs
--memory/--cpus Resource limits

Secrets Management

Never embed secrets in images:

# Bad - secret in environment variable visible in image layers
ENV API_KEY=secret123

# Good - mount secrets at runtime
docker run -v /secrets/api_key:/run/secrets/api_key:ro myapp

# Better - use Docker secrets (Swarm) or external secret manager
docker secret create api_key ./api_key.txt
docker service create --secret api_key myapp

Container Security Checklist

Category Control Implementation
Images Use minimal base images distroless, alpine, slim
Images Scan for vulnerabilities Trivy, Snyk, cloud-native
Images Sign and verify Cosign, Notary
Runtime Run as non-root USER directive
Runtime Drop capabilities --cap-drop ALL
Runtime Read-only filesystem --read-only
Secrets External management Vault, cloud secrets
Logging Centralized logging Fluentd, cloud logging

Next, we'll secure Kubernetes clusters with RBAC, network policies, and pod security. :::

Quiz

Module 5: Container & Kubernetes Security

Take Quiz