A Docker image is not just a packaging step. It is a production artifact that carries application code, dependencies, metadata, defaults, and sometimes secrets or assumptions about identity and the host. Before the first build, a team should know which base it trusts, what enters the build context, how dependencies are pinned, how provenance is recorded, and what the runtime is allowed to do. Docker build best practices and NIST's Application Container Security Guide both point toward treating image creation and operation as a lifecycle. The related guide on Docker images in production extends that thinking into rollout and maintenance.
Write the image contract
An image contract states what the image contains, how it is built, which architectures it supports, what user it runs as, what ports or files it expects, and how it receives configuration. It should also say what the image does not contain: credentials, development tools, mutable state, or unreviewed network access. This contract helps application, security, and operations teams review the same artifact. It also makes the build reproducible enough to investigate why two releases differ. Use a stable tag for human navigation, but deploy an immutable digest or equivalent version identity so a workload cannot silently receive a different image later.

| Image decision | Why it matters | Evidence to retain |
|---|---|---|
| Base image | Sets libraries, attack surface, and update path | Digest, publisher, version policy, and review. |
| Build context | Determines what the builder can see and copy | Ignore rules, context boundary, and secret handling. |
| Dependencies | Influences reproducibility and known vulnerabilities | Lock files, checksums, and resolution record. |
| Runtime identity | Limits what a compromised process can do | User, capabilities, filesystem, and network policy. |
| Artifact identity | Makes deployment and rollback unambiguous | Digest, source revision, builder, and provenance. |
Choose a base and build context
Select a base image for supportability and risk, not only size. A minimal image can reduce packages but may make debugging and patching harder if the team does not understand its contents. Record the exact digest and establish who publishes updates. Keep the build context narrow with an appropriate ignore file; a large context slows builds and increases the chance that local files, credentials, test data, or generated artifacts are copied into a layer. Use multi-stage builds to separate compilation tools from the runtime image. Review every copy instruction as a data-flow decision rather than assuming that a later delete removes a secret from the image history.
- Pin the base by digest and define how it will be refreshed.
- Keep build context limited to files required for the artifact.
- Use multi-stage builds to exclude compilers and test tooling from runtime.
- Never pass secrets through a build argument or a layer that can be inspected later.
- Record the source revision and builder identity with the image.
Make runtime identity explicit
The image should not assume root access unless the workload has a documented reason and compensating controls. Define the user, group, filesystem write locations, Linux capabilities, network access, and signal behavior. Docker Engine security explains why the daemon and host boundary matter; a safe image cannot compensate for an unrestricted runtime. Kubernetes image guidance also makes the deployment reference and pull behavior part of the operational picture. Test the image with the same identity and restrictions it will have in production, because a container that only works as root has not completed the design.
Scan with a response plan
Vulnerability scanning is useful only when a finding leads to a decision. Define severity thresholds, exceptions, ownership, and the time allowed for remediation. Distinguish a vulnerable package that is reachable in the runtime from one present only in a discarded build stage, while still understanding the limits of that distinction. Track false positives and compensating controls. NIST SP 800-190 describes container-specific risks across images, registries, orchestration, and hosts. That lifecycle view prevents teams from treating a clean scan as proof that the deployment is safe or a single CVE as a complete risk score.
| Finding | First question | Possible action |
|---|---|---|
| Critical runtime CVE | Is the affected code present and reachable? | Block release, patch base or dependency, and retest. |
| Unknown provenance | Can the image be traced to source and builder? | Quarantine it until identity evidence exists. |
| Secret-like file | Did it enter a layer, history, or registry? | Revoke the secret, rebuild, and check derived copies. |
| Root runtime | Does the application truly require it? | Drop privileges and test with an explicit service user. |
| Stale base | Is the update path owned and exercised? | Refresh on a defined cadence and record the result. |
Preserve provenance and promotion
An image should be promoted through environments without being rebuilt from different inputs at each stage. Attach source revision, dependency resolution, base digest, build system, timestamp, and test results to the artifact. Sign or otherwise attest to the identity in a way the deployment system can verify. Use registry access controls and retention rules that match the sensitivity of the artifact. Promotion should reference the same immutable artifact that was tested. If an image is rebuilt for production, the team needs a new evidence record rather than assuming that the source was unchanged.
Refresh and retire images
Image maintenance is a queue of decisions about base updates, application dependencies, operating system patches, and end-of-life components. Set an update trigger, owner, test path, and rollback plan. Rebuild regularly enough to avoid a large jump between versions, but do not hide the reason for a rebuild. Remove unused tags and revoke access to retired artifacts according to policy. Measure time from vulnerability disclosure to patched deployment, age of running images, failed refreshes, and the number of images without an owner. An image inventory without an active refresh path is an archive of risk.
Make the image reproducible and searchable
Reproducibility is easier when the build has a small, explicit input set. Pin package versions, record the package manager resolution, control the build environment, and avoid downloading unverified content during a build. Build caches can improve speed, but a cache should not silently provide a dependency that the current inputs do not declare. Keep a way to rebuild from a clean environment and compare the resulting digest or explain expected differences. The goal is not that every byte is identical in every ecosystem; it is that the team can account for the artifact it promotes.
An inventory should include more than image names. Track digest, repository, source revision, base, architecture, owner, environment, running workload, exposure, and end-of-life date. Generate a software bill of materials or equivalent component record and connect findings to the deployed digest. This makes a vulnerability response faster because the team can identify where the affected component is running instead of searching by a mutable tag. Inventory also helps retire abandoned images and discover duplicate build pipelines that have drifted apart.
Registry controls deserve the same attention as runtime controls. Limit who can push, overwrite, pull, delete, or promote images. Separate build and deployment credentials, use short-lived access where possible, and monitor unusual pulls or tag changes. Retention should preserve the artifacts needed for rollback and investigation without keeping every intermediate layer forever. If a registry is compromised, the response should include checking provenance, rotating credentials, and verifying running workloads against known-good identities.
Multi-architecture support introduces another identity question. A tag may point to different architecture-specific manifests, and an image that passes on one platform may fail or behave differently on another. Test each supported architecture, record the manifest identity, and make the deployment scheduler's assumptions explicit. Do not expand support simply because the build succeeded. Runtime libraries, native extensions, performance, and security scanning coverage may differ. The image contract should name supported platforms and the evidence behind that claim.
Runtime tests should exercise the container as an operator will use it. Start it with the declared user, read-only filesystem where intended, restricted capabilities, network policy, health checks, and resource limits. Verify graceful termination, signal handling, log behavior, and failure when a required configuration is missing. These tests catch images that are clean in a scanner but unsafe or unreliable in the actual orchestrator. Treat a failed runtime contract as a build failure, because remediation is cheaper before promotion than during an incident.
The build pipeline should make the secure path the easy path. Provide a maintained base catalog, approved builders, dependency scanning, secret checks, provenance generation, and a documented exception process. A developer should be able to see why a build failed and what evidence is needed to proceed. Exceptions need an owner and expiry; otherwise a temporary risk becomes a permanent gap. Central controls are helpful when they reduce repeated work while still allowing an application team to understand the artifact it is deploying.
Recovery from an image issue may involve more than redeploying an older tag. Identify running digests, stop vulnerable workloads, rotate credentials if the image may have exposed them, inspect registry access, and check derived caches or deployment manifests. Preserve the affected artifact for investigation according to policy. Run this scenario as an exercise so the team knows which inventory, registry, orchestrator, and security tools are needed. A trusted image process is measured by how quickly it can contain and explain a bad artifact.
Image policy should distinguish development convenience from production authorization. A local image may use a broad toolchain or a mutable tag while an approved production image needs a restricted base, verified provenance, and a least-privileged runtime. Make the promotion boundary explicit so teams know which checks apply at each stage. This avoids both extremes: blocking useful local iteration with controls that belong later, or allowing a development shortcut to become an undocumented production dependency.
The image contract should name the health and shutdown behavior that the orchestrator expects. A process that does not handle termination can lose work during a rollout, while a weak health check can keep an unhealthy container in service. Define readiness, liveness, startup, graceful drain, and resource expectations with the workload owner. Test these behaviors under the same limits used in production. Security and reliability meet at this boundary because a container that cannot stop or report state cleanly is harder to contain during an incident.
Document the operator's first five minutes after an image alert. The runbook should identify affected digests, owners, workloads, exposure, registry history, and the safest containment action. Include commands or console views that use least privilege and links to the rebuild and promotion path. Review the runbook after an exercise or incident and remove steps that depend on one person's memory. Image security becomes repeatable when inventory, response, and recovery are connected to the same artifact identity.
Frequently asked questions
Question: Is an SLO the same as an infrastructure metric? Answer: No; it measures an important user-facing outcome through a defined indicator and target. Question: What should happen when the error budget burns quickly? Answer: Follow a policy that changes delivery, investigation, or recovery work according to the consequence and evidence.
What should a Docker image contract specify?
Answer: It should specify base, build inputs, dependencies, user identity, exposed interfaces, configuration, provenance, scanning, and update ownership.
Why avoid mutable image tags?
Answer: A mutable tag can point to different bytes over time, making testing, promotion, rollback, and incident attribution less reliable than an immutable digest.
How should image vulnerabilities be handled?
Answer: Assess reachability and severity, patch or rebuild, block promotion when policy requires it, and keep a supported rollback image with known provenance.
What is the best first investment in Docker images? Establish an image contract, pin the base and dependencies, and make runtime identity explicit. Compare container security decisions and Kubernetes deployments when the image will run in a shared orchestrator. Does a minimal image remove security work? No; it changes the attack surface but does not solve provenance, patching, host, or runtime concerns. Should images use floating tags? Use readable tags for humans but deploy immutable digests for repeatability. How often should images be rebuilt? On security or base updates and on a cadence that keeps the dependency state supportable. Can a scanner approve an image by itself? No. Security is a lifecycle judgment that combines evidence, reachability, runtime controls, and ownership.
Key takeaways
- Define what an image contains, excludes, expects, and permits before building it.
- Pin and record base images, dependencies, source, builder, and artifact identity.
- Keep build context narrow and keep secrets out of every layer and history.
- Run as a least-privileged identity with explicit filesystem, capability, and network controls.
- Connect scanning and provenance to ownership, refresh, promotion, and retirement decisions.
Conclusion
Docker images are dependable production units when their inputs and boundaries are known. Choose a supportable base, control the context, preserve provenance, limit runtime authority, and maintain a response path for vulnerabilities and drift. Those decisions make the first build easier to trust and every later refresh easier to explain.