Study notes · 9% of the exam

Image and Runtime Security

Container security is layered: run with the least privilege, ship the least software, keep secrets out of images, and verify what you deploy. Most incidents come from one setting that quietly undoes the rest, such as a mounted Docker socket or `--privileged`.

Key points

  1. 1

    Images run as root unless they set USER or you pass --user. Without user namespaces, that is UID 0 on the host kernel too, so default to a non-root UID.

  2. 2

    Docker drops many capabilities by default. Go further with --cap-drop ALL plus only what you need, and treat CAP_SYS_ADMIN and --privileged as nearly full host access.

  3. 3

    Access to the Docker socket, the docker group or an unauthenticated TCP API all mean root on the host. Remote access should use SSH or TLS with --tlsverify.

  4. 4

    Never put secrets in ENV, ARG or copied files: they persist in layers, history and max-mode provenance. Use BuildKit secret or SSH mounts for builds, and runtime secrets mounted under /run/secrets.

  5. 5

    Cheap runtime hardening: --read-only with --tmpfs for scratch, --security-opt no-new-privileges, the default seccomp profile, and --memory and --pids-limit limits.

  6. 6

    Supply chain: pin base images by digest, verify signatures (cosign), produce SBOM and provenance attestations, scan continuously, and rebuild when bases are patched.

  7. 7

    Rootless mode runs the daemon itself as a normal user. Low ports need CAP_NET_BIND_SERVICE on rootlesskit or a sysctl, and limits need cgroup v2 with systemd.

Common traps

  • Deleting a secret in a later layer does not remove it from the earlier layer that added it.

  • Mounting the Docker socket with :ro still allows every API call.

  • Published ports bypass ufw rules; bind to 127.0.0.1 or filter in the DOCKER-USER chain.

Test yourself on Image and Runtime Security

Ten questions, with the answer and explanation after each one.