Don't run as root
-
By default a container's process is root (inside the container)
-
Add a non-root user in the Dockerfile:
RUN useradd -m appuser
USER appuser
-
Drop Linux capabilities you don't need
Handle secrets carefully
- Never bake passwords/keys into an image (they're in the layers)
- Pass secrets at runtime (env vars, mounted files, secret stores)
- Assume anything in the image is readable by anyone with the image
Rootless & Podman
- Rootless Docker/containers run the daemon as a normal user —
a container escape doesn't land as host root
- Podman is daemonless and rootless by design, and CLI-compatible
(alias docker=podman often just works)
SBOM & signing
- SBOM — a software bill of materials: everything in the image
- Signing — prove an image is really yours and untampered
- Increasingly required in real CI/CD supply chains
Runtime hardening (quick list)
- Read-only root filesystem where possible
- Drop capabilities; no
--privileged unless truly needed
- Set memory/CPU limits so one container can't starve the host
- Keep the host and engine patched
Lab goals
- Scan one of your images and fix or explain the findings
- Rebuild it to run as a non-root user
- Show that a hardcoded secret is visible in the image history, then
move it to a runtime env var