ESC
Type to search guides, tutorials, and reference documentation.
Verified by Garnet Grid

Container Security Hardening

Secure containerized applications from image building to runtime. Covers image scanning, minimal base images, rootless containers, runtime security, Kubernetes security contexts, network policies, and the patterns that protect containerized workloads.

Containers share the host kernel, which means a container escape can compromise every workload on the node. Container security requires defense in depth — securing the image, the build pipeline, the runtime, and the orchestrator. A single misconfigured container can be your weakest link.


Image Security

# BAD: Fat image, runs as root, no scanning
FROM ubuntu:latest
RUN apt-get update && apt-get install -y python3 python3-pip
COPY . /app
RUN pip3 install -r /app/requirements.txt
CMD ["python3", "/app/main.py"]

# GOOD: Minimal image, non-root, pinned versions
FROM python:3.12-slim@sha256:abc123... AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

FROM python:3.12-slim@sha256:abc123...
RUN groupadd -r appuser && useradd -r -g appuser appuser
WORKDIR /app
COPY --from=builder /install /usr/local
COPY --chown=appuser:appuser . .
USER appuser
HEALTHCHECK --interval=30s CMD curl -f http://localhost:8080/health || exit 1
CMD ["python", "main.py"]

# Image size comparison:
# ubuntu:latest + python = ~450MB, 200+ CVEs
# python:3.12-slim        = ~120MB, 15-30 CVEs
# python:3.12-alpine      = ~50MB,  5-10 CVEs
# distroless/python3       = ~30MB, 0-5 CVEs

Image Scanning

# CI/CD Pipeline: Scan before pushing
name: Container Security
on: [push]

jobs:
  scan:
    steps:
      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .
      
      - name: Trivy vulnerability scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          severity: "CRITICAL,HIGH"
          exit-code: "1"  # Fail pipeline on critical/high CVEs
      
      - name: Dockle best practices
        run: dockle myapp:${{ github.sha }}
      
      - name: Cosign sign image
        run: cosign sign --key cosign.key myapp:${{ github.sha }}

Kubernetes Security Context

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
        seccompProfile:
          type: RuntimeDefault
      
      containers:
        - name: app
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: ["ALL"]
          
          # Read-only root needs writable paths
          volumeMounts:
            - name: tmp
              mountPath: /tmp
            - name: cache
              mountPath: /app/.cache
      
      volumes:
        - name: tmp
          emptyDir: {}
        - name: cache
          emptyDir: {}

Network Policies

# Default deny all ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: production
spec:
  podSelector: {}  # Apply to all pods
  policyTypes: ["Ingress", "Egress"]

# Allow only specific traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-to-db
spec:
  podSelector:
    matchLabels:
      app: database
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api-server
      ports:
        - port: 5432
          protocol: TCP

Anti-Patterns

Anti-PatternConsequenceFix
Running as rootContainer escape = root on hostUSER directive in Dockerfile
latest tagUnpredictable, unauditablePin image digest, scan on pull
No network policiesAny pod can reach any podDefault deny + explicit allow
Writable root filesystemMalware can modify containerreadOnlyRootFilesystem: true
No runtime monitoringPost-exploitation undetectedFalco, Aqua, Sysdig for runtime detection

Container security is not a single tool — it is a lifecycle practice from image building through runtime. Every layer you secure reduces the blast radius of a breach.

Jakub Dimitri Rezayev
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting

Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.

View Full Profile →