FixTheVuln

Container Security Cheat Sheet

By FixTheVuln Team Peer-reviewed security content Sources: CISA, NVD, OWASP

Key Takeaways

Test Your Knowledge

CKA Practice Quiz CKS Practice Quiz

Latest from the Blog

AWS Cloud Practitioner Study Guide: How to Pass the CLF-C02 Exam CompTIA Cloud+ Study Guide: Everything You Need to Pass the CV0-004... Google Cloud ACE Study Guide: Everything You Need to Pass the ACE Exam
← Back to Home

Container Security Essentials

Quick reference for securing Docker containers, Kubernetes clusters, and container registries. Covers image hardening, runtime security, and orchestration best practices.

Docker Security Hardening

1. Image Security

# Use minimal base images
FROM alpine:3.18
# or
FROM gcr.io/distroless/static-debian11

# Don't run as root
RUN addgroup -g 1000 appgroup && \
    adduser -u 1000 -G appgroup -D appuser
USER appuser

# Use specific versions, not 'latest'
FROM node:20.10.0-alpine3.18

# Multi-stage builds to reduce attack surface
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o myapp

FROM scratch
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]

2. Dockerfile Best Practices

# Bad - running as root
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y nginx
CMD ["nginx", "-g", "daemon off;"]

# Good - non-root user, minimal image
FROM nginx:1.25-alpine
RUN addgroup -g 101 -S nginx && \
    adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx nginx
USER nginx
COPY --chown=nginx:nginx nginx.conf /etc/nginx/nginx.conf
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]

3. Docker Daemon Security

# /etc/docker/daemon.json
{
  "icc": false,
  "userns-remap": "default",
  "no-new-privileges": true,
  "live-restore": true,
  "userland-proxy": false,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2"
}

4. Runtime Security Flags

# Run container with security options
docker run -d \
  --name secure-app \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=100m \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  --security-opt no-new-privileges:true \
  --security-opt seccomp=/path/to/seccomp-profile.json \
  --pids-limit 100 \
  --memory 512m \
  --cpus 0.5 \
  --user 1000:1000 \
  --network custom-network \
  myapp:latest

Kubernetes Security

1. Pod Security Standards

# Restricted Pod Security Standard
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp:v1.0.0
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
          - ALL
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
      requests:
        memory: "64Mi"
        cpu: "250m"
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir: {}

2. Network Policies

# Default deny all ingress traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress

---
# Allow specific ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

3. RBAC Configuration

# Least privilege Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get"]

---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production
subjects:
- kind: ServiceAccount
  name: monitoring-sa
  namespace: production
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

4. Secrets Management

# Use external secrets operator (not plain K8s secrets)
# Example with External Secrets Operator
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: db-credentials
    creationPolicy: Owner
  data:
  - secretKey: username
    remoteRef:
      key: secret/data/production/db
      property: username
  - secretKey: password
    remoteRef:
      key: secret/data/production/db
      property: password

Image Scanning & Registry Security

1. Trivy Scanner

# Scan image for vulnerabilities
trivy image myapp:latest

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

# Scan and fail on vulnerabilities (for CI/CD)
trivy image --exit-code 1 --severity CRITICAL myapp:latest

# Scan Dockerfile
trivy config Dockerfile

# Scan Kubernetes manifests
trivy config --severity HIGH,CRITICAL ./k8s/

# Generate SBOM
trivy image --format spdx-json -o sbom.json myapp:latest

2. Grype Scanner

# Scan image
grype myapp:latest

# Scan with output format
grype myapp:latest -o json > vulnerabilities.json

# Fail on severity
grype myapp:latest --fail-on critical

# Scan SBOM
grype sbom:./sbom.json

3. CI/CD Integration (GitHub Actions)

name: Container Security Scan

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Build image
      run: docker build -t myapp:${{ github.sha }} .

    - name: Run Trivy vulnerability scanner
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: 'myapp:${{ github.sha }}'
        format: 'sarif'
        output: 'trivy-results.sarif'
        severity: 'CRITICAL,HIGH'
        exit-code: '1'

    - name: Upload Trivy scan results
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: 'trivy-results.sarif'

4. Registry Security

# Sign images with cosign
cosign generate-key-pair
cosign sign --key cosign.key myregistry.com/myapp:v1.0.0

# Verify signed image
cosign verify --key cosign.pub myregistry.com/myapp:v1.0.0

# Use admission controller to enforce signed images
# Kyverno policy example
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  background: false
  rules:
  - name: verify-signature
    match:
      any:
      - resources:
          kinds:
          - Pod
    verifyImages:
    - imageReferences:
      - "myregistry.com/*"
      attestors:
      - entries:
        - keys:
            publicKeys: |-
              -----BEGIN PUBLIC KEY-----
              ...
              -----END PUBLIC KEY-----

Runtime Security

1. Falco Rules

# /etc/falco/falco_rules.local.yaml
- rule: Detect Shell in Container
  desc: Detect shell spawned in container
  condition: >
    spawned_process and
    container and
    shell_procs
  output: >
    Shell spawned in container
    (user=%user.name container=%container.name
    shell=%proc.name parent=%proc.pname)
  priority: WARNING
  tags: [container, shell]

- rule: Detect Crypto Mining
  desc: Detect crypto mining processes
  condition: >
    spawned_process and
    container and
    (proc.name in (cryptominer_binaries) or
     proc.cmdline contains "stratum+tcp")
  output: >
    Crypto mining detected
    (container=%container.name command=%proc.cmdline)
  priority: CRITICAL
  tags: [container, cryptomining]

2. AppArmor Profile

# /etc/apparmor.d/docker-custom
#include 

profile docker-custom flags=(attach_disconnected,mediate_deleted) {
  #include 

  network,
  capability,

  deny @{PROC}/* w,
  deny @{PROC}/sys/kernel/** w,
  deny /sys/** w,

  deny /bin/su x,
  deny /usr/bin/sudo x,
  deny /bin/bash x,
  deny /bin/sh x,

  /app/** r,
  /app/bin/* ix,
  /tmp/** rw,
}

# Load profile
sudo apparmor_parser -r /etc/apparmor.d/docker-custom

# Use in Docker
docker run --security-opt apparmor=docker-custom myapp:latest

3. Seccomp Profile

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": [
        "accept", "access", "arch_prctl", "bind", "brk",
        "clone", "close", "connect", "dup", "dup2",
        "execve", "exit", "exit_group", "fcntl", "fstat",
        "futex", "getdents64", "getpid", "getsockname",
        "getsockopt", "listen", "lseek", "mmap", "mprotect",
        "munmap", "nanosleep", "open", "openat", "pipe",
        "poll", "read", "recvfrom", "rt_sigaction",
        "rt_sigprocmask", "sendto", "set_tid_address",
        "setsockopt", "socket", "stat", "write"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

Container Security Checklist

Category Check Priority
Images Use minimal base images (Alpine, Distroless) High
Images Pin image versions, avoid 'latest' tag High
Images Scan images for vulnerabilities in CI/CD Critical
Images Sign and verify images High
Runtime Run containers as non-root user Critical
Runtime Use read-only root filesystem High
Runtime Drop all capabilities, add only needed High
Runtime Set resource limits (CPU, memory, PIDs) Medium
Kubernetes Implement Pod Security Standards Critical
Kubernetes Use Network Policies (default deny) High
Kubernetes Configure RBAC with least privilege Critical
Kubernetes Use external secrets management High
Registry Use private registry with authentication High
Registry Enable vulnerability scanning on push High
Monitoring Deploy runtime security (Falco, Sysdig) Medium
Monitoring Enable audit logging High

Related Resources

☁️ Cloud Security AWS, Azure, GCP security 🐧 Linux Hardening Linux server security 🔐 Secrets Management Secure credential storage

Need Detailed Container Security Guides?

For comprehensive tutorials and step-by-step implementation guides:

Visit FixTheVuln.com →

FixTheVuln Store

Get the Kubernetes CKS Study Planner

Fillable PDF study planners with domain trackers, weekly schedules, and progress tracking. Available in Standard, ADHD-Friendly, Dark Mode, and 4-Format Bundle.

Kubernetes CKS Planner

60+ certifications available — from $5.99

CyberFolio

Choosing your next cert? Track them all in one place.

Build a shareable cybersecurity portfolio that highlights your certifications, projects, and skills — free.

Build Your Portfolio →