Container Image & Runtime Checklist
Build an image that is small, reproducible and safe to run, the build rules that matter, what must never be baked in, and the runtime settings that are wrong by default.
Markdown. No sign-up, no email.
Image / service: _______________ Date: _______
1. Base image#
- [ ] Pinned by digest, not by tag, a tag moves, a digest does not
- [ ] Minimal base chosen deliberately (distroless, slim, alpine) with the reason recorded
- [ ] Base image comes from a source you would name in an audit
- [ ] Base updated on a schedule, not when something breaks
- [ ] Not
latestanywhere in the file
An image built from
FROM node:latestis a different image every week. The version running is not the version anyone approved.
2. Build#
- [ ] Multi-stage build. Build tools do not reach the final image
- [ ] Dependency install is its own layer, before the source copy, so the cache survives a code change
- [ ]
.dockerignorepresent,.git,node_modules, secrets, test fixtures - [ ] Build is reproducible: same inputs, same image
- [ ] No
apt-get upgradein the build, upgrade the base instead, or the image drifts - [ ] Package lists cleaned in the same layer they were created
3. Secrets: what must never be in an image#
- [ ] No credentials in
ENV,ARG, or any layer. Layers are readable by anyone with the image, including deleted files - [ ] No
.envfile copied in - [ ] No private keys, certificates or tokens
- [ ] No
.gitdirectory - [ ] Build-time secrets use the build secret mount, not
ARG - [ ] Image scanned for secrets in the pipeline
A secret added in one layer and deleted in the next is still in the image. Deletion adds a layer; it does not remove one.
4. Runtime identity and filesystem#
- [ ] Runs as a non-root user, created in the image
- [ ]
USERset, the default is root and the default is wrong - [ ] Read-only root filesystem, with writable volumes only where needed
- [ ] No
--privileged - [ ] Capabilities dropped, then added back only if required
- [ ]
no-new-privilegesset
5. Size and layers#
- [ ] Final image size recorded and justified
- [ ] Nothing installed that is not needed at runtime, no compilers, no shells you do not use
- [ ] Layers ordered least-changing to most-changing
- [ ] Image inspected once by hand, you know what is in it
6. Configuration#
- [ ] Configuration from environment or a mounted file, never baked in
- [ ] The same image runs in every environment
- [ ] Sensible defaults, with required values failing loudly at startup rather than defaulting to something wrong
7. Process behaviour#
- [ ] One process concern per container
- [ ] Process runs in the foreground, PID 1 handles signals, or an init is used
- [ ] Responds to SIGTERM and shuts down cleanly within the grace period
- [ ] In-flight work is finished or handed back on shutdown
- [ ] Logs to stdout and stderr, not to files inside the container
A container that ignores SIGTERM is killed after the grace period. Every rolling update then drops whatever it was doing.
8. Health and resources#
- [ ] Readiness check. Can it serve right now?
- [ ] Liveness check. The process only, never a dependency
- [ ] Memory limit set, from measurement
- [ ] CPU request set, from measurement
- [ ] Behaviour under the memory limit understood, a runtime that does not see the limit will exceed it
9. Supply chain#
- [ ] Image scanned for known vulnerabilities in the pipeline, and the result blocks
- [ ] Dependency manifest committed and reviewed
- [ ] Image signed, or its digest recorded in the deployment record
- [ ] Registry access controlled and audited
- [ ] Retention policy on old images, registries grow without limit
10. The traps#
- [ ] Not treating the container as a small server, no SSH, no cron inside, no manual fixes
- [ ] No state on the container filesystem. It is gone on restart
- [ ] Not running as root because it was easier
- [ ] Not copying the whole build context because
.dockerignorewas skipped - [ ] Not using the same image with an environment variable that changes behaviour dangerously
Sign-off#
| Name | Date | |
|---|---|---|
| Built by | ||
| Reviewed by |