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, usedocker buildx imagetools inspect <ref> --format '{{ json . }}'ordocker scout sbom <ref>.