Module 3 of 16

Containers & Workload Security

Hardening containers from image build to runtime with Pod Security Standards, seccomp, and distroless images

3 hours3 labsFree

Start here

Learning objectives

  • Understand Linux container isolation primitives (namespaces, cgroups)
  • Build secure container images with distroless and rootless patterns
  • Configure Pod Security Standards for cluster-wide enforcement
  • Implement seccomp and capabilities restrictions
CONTAINER ISOLATION vs CONTAINER ESCAPEProperly Isolated ContainerPID NamespaceNetwork NamespaceMount NamespaceUser NamespaceSeccomp + AppArmor + Capabilities DropNon-root user | Read-only FS | No hostPIDResult: strong isolation from hostContainer Escape Scenarioprivileged: true (ALL capabilities)hostPID: true (sees host processes)hostNetwork: true (host network stack)Root user | Writable FS | No seccompResult: trivial escape to host

Containers are not VMs. They share the host kernel and rely on Linux primitives — namespaces, cgroups, seccomp, capabilities — for isolation. Misconfigure any of these, and the container boundary dissolves.

Linux Container Isolation Primitives

  • Namespaces: Isolate what a container can see (PID, network, mount, user, IPC, UTS)
  • cgroups: Limit what a container can use (CPU, memory, I/O)
  • Seccomp: Filter which syscalls a container can make (block dangerous ones like ptrace, mount)
  • Capabilities: Fine-grained root privileges (drop everything except what is needed)
  • AppArmor/SELinux: Mandatory access control for file and network operations

Secure Container Image Patterns

# Insecure: full OS, root user, unnecessary tools
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl wget vim
COPY app /app
CMD ["/app"]

# Secure: distroless, non-root, minimal attack surface
FROM gcr.io/distroless/static-debian12:nonroot
COPY --chown=65534:65534 app /app
USER 65534
ENTRYPOINT ["/app"]
# No shell, no package manager, no curl, no wget
# Attacker with RCE cannot spawn a shell

Pod Security Standards

Kubernetes defines three Pod Security Standards that enforce container hardening at the namespace level:

  • Privileged: No restrictions (for system workloads only)
  • Baseline: Prevents known privilege escalations (blocks hostPID, hostNetwork, privileged)
  • Restricted: Maximum hardening (requires non-root, read-only root FS, drops ALL capabilities)
# Enforce restricted Pod Security Standard on a namespace
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/audit: restricted

Real world

Where this shows up

  • Hardening container images for production
  • Implementing Pod Security Standards cluster-wide
  • Building distroless CI pipelines
  • Container escape prevention in multi-tenant clusters

Production notes

Keep these close

  • Use distroless or scratch base images for all production workloads. A container with no shell cannot be used for interactive exploitation.
  • Apply the restricted Pod Security Standard to all production namespaces. Use warn mode first to identify non-compliant workloads before enforcing.

Common mistakes

What usually breaks

  • Running containers as root (the default in most base images)
  • Using ubuntu or alpine base images that include shells and package managers
  • Not dropping ALL capabilities and adding back only what is needed
  • Setting privileged: true "just to make it work" and never removing it
  • Not enforcing Pod Security Standards on production namespaces

Security risks

Threats to watch

  • privileged: true gives the container ALL capabilities including CAP_SYS_ADMIN — equivalent to root on the host
  • hostPID exposes all host processes to the container — enables credential theft from other pods
  • hostNetwork puts the container on the host network stack — bypasses all NetworkPolicies

Key terms

Vocabulary used in this module

Namespace (Linux)

Kernel feature that isolates what a process can see (PID, network, mount, etc.)

cgroup

Control group — limits CPU, memory, and I/O resources for a set of processes

Seccomp

Secure computing mode — filters which syscalls a process can make

Distroless

Container image containing only the application binary and runtime — no OS tools

Pod Security Standard

Kubernetes policy level (Privileged/Baseline/Restricted) for container hardening

Labs

Hands-on labs

30 minBeginner

Harden an Insecure Container

Transform an insecure Dockerfile into a hardened production image.

  1. Start with a vulnerable Dockerfile (root, full OS, unnecessary tools)
  2. Rebuild with distroless base image
  3. Add non-root user and read-only filesystem
  4. Compare image sizes and attack surfaces
View lab on GitHub
25 minBeginner

Configure Pod Security Standards

Enforce container hardening at the namespace level.

  1. Label a namespace with restricted Pod Security Standard
  2. Deploy a compliant pod (succeeds)
  3. Deploy a non-compliant pod with hostPID (rejected)
  4. Review audit logs for policy violations
View lab on GitHub
30 minIntermediate

Container Escape Demonstration

Understand how misconfigurations enable container escape.

  1. Deploy a privileged container with hostPID
  2. Access host processes from inside the container
  3. Read host filesystem via /proc/1/root
  4. Fix the configuration and verify isolation is restored
View lab on GitHub

Recap

Key takeaways

  • Containers share the host kernel — isolation depends on namespaces, cgroups, seccomp
  • Distroless images eliminate shells and tools, drastically reducing attack surface
  • Pod Security Standards enforce container hardening at the namespace level
  • Never run containers as root or with privileged: true in production
  • Seccomp profiles block dangerous syscalls — always enable the default profile

Related resources

Keep learning across CodersSecret