Frontend Labs
⋯

8. Docker security and the software supply chain

Container security comes down to three questions. What's in the image (vulnerabilities, secrets)? Who built it (provenance, signatures)? And what can it do at runtime (privileges)?

8.1 Runtime hardening checklist

Control Docker flag Kubernetes field (§34)
Non-root user --user 65532 runAsNonRoot: true, runAsUser
Drop capabilities --cap-drop ALL capabilities.drop: ["ALL"]
No privilege escalation --security-opt no-new-privileges allowPrivilegeEscalation: false
Read-only root FS --read-only readOnlyRootFilesystem: true
Seccomp default profile is on seccompProfile.type: RuntimeDefault
Resource limits --memory --cpus --pids-limit resources.limits
Never --privileged, -v /var/run/docker.sock, --pid=host, --net=host privileged, hostPID, hostNetwork, hostPath

Rootless mode (dockerd-rootless-setuptool.sh install, or Podman by default) runs the daemon itself as a normal user, so a container escape lands as an unprivileged user.

8.2 Scanning images

trivy image --severity HIGH,CRITICAL --ignore-unfixed orbit-catalog:0.1.0
trivy image --exit-code 1 --severity CRITICAL orbit-catalog:0.1.0   # CI gate
trivy fs --scanners secret,misconfig .                              # secrets + Dockerfile/K8s misconfig
docker scout cves orbit-catalog:0.1.0                               # Docker's scanner

Best practice: gate CI on CRITICAL with a fix available, not on every finding. A gate nobody can pass gets disabled. Track the rest with a scheduled re-scan of what's actually running: new CVEs are published against images you shipped last month.

8.3 SBOMs, provenance, and signing

# Build with SBOM + SLSA provenance attestations attached to the image in the registry
docker buildx build --platform linux/amd64,linux/arm64 \
  --sbom=true --provenance=mode=max \
  -t ghcr.io/acme/orbit-orders:$(git rev-parse --short HEAD) --push .

# Inspect the SBOM later (e.g. "are we affected by the new CVE in libfoo?")
docker buildx imagetools inspect ghcr.io/acme/orbit-orders:abc123 --format '{{ json .SBOM }}'

# Sign by DIGEST with Sigstore cosign (keyless in CI via OIDC; key-based shown here)
cosign generate-key-pair
cosign sign --key cosign.key ghcr.io/acme/orbit-orders@sha256:<digest>
cosign verify --key cosign.pub ghcr.io/acme/orbit-orders@sha256:<digest>

In CI you'll use keyless signing: the GitHub Actions OIDC token proves "this image was built by workflow X in repo Y", and in Part VI a Kyverno policy refuses to run anything that isn't signed that way (§34.6).

Real-world example: after the 2020 SolarWinds and 2021 Codecov incidents, "prove where this binary came from" became a compliance requirement (US EO 14028, SLSA). SBOM + provenance + signature verification at admission is now the expected baseline at regulated companies.

⚠️ Caveat (verify): the imagetools inspect --format '{{ json .SBOM }}' template depends on the Buildx version and on the SBOM having been attached. If it prints nothing, use docker buildx imagetools inspect <ref> --format '{{ json . }}' or docker scout sbom <ref>.


Generated from real-life-k8s-guide.md · 8 Oct 2026 16:36