17.1.2.2 Base Version Pinning
A focused guide to Base Version Pinning, connecting core concepts with practical Docker and container operations.
Base version pinning addresses the specific decisions and complications around fixing a Dockerfile's FROM reference to an exact, verifiable base image, going beyond the basic tag-versus-digest choice into multi-architecture digest behavior, signature verification, and how automated tooling can keep a pinned digest current without sacrificing the certainty pinning is meant to provide.
The multi-architecture digest complication
A single image tag like node:20 actually corresponds to a manifest list containing several different, architecture-specific image digests, one for amd64, one for arm64, and so on, which means pinning to a single, specific digest fixes the build to exactly one of those architecture variants rather than to the tag's full, multi-architecture identity:
docker buildx imagetools inspect node:20
Name: docker.io/library/node:20
MediaType: application/vnd.oci.image.index.v1+json
Manifests:
Name: docker.io/library/node:20@sha256:abc... Platform: linux/amd64
Name: docker.io/library/node:20@sha256:def... Platform: linux/arm64
Pinning a Dockerfile's FROM instruction to one of these specific, per-platform digests breaks multi-platform builds entirely for any other architecture, since that exact digest simply does not exist or apply to a different platform; for projects that need to build for multiple architectures, pinning needs to reference the manifest list's own digest, not one of its individual platform-specific entries, to preserve correct multi-architecture resolution.
FROM node:20@sha256:<manifest-list-digest>
Confirming which digest, the manifest list's own top-level digest versus an individual platform-specific one, is actually being referenced is worth verifying explicitly, since both are valid-looking digest strings that resolve to genuinely different scopes of content.
Verifying image signatures alongside digest pinning
Digest pinning guarantees content immutability, the referenced content cannot silently change, but it does not by itself verify the content's authenticity or provenance; image signing and verification, through tools like cosign, provides a complementary guarantee that the pinned digest actually corresponds to an image genuinely published by its claimed, trusted source:
cosign verify --key cosign.pub registry.example.com/my-api@sha256:3f29a8c1...
docker trust inspect node:20
Combining digest pinning with signature verification in an automated build pipeline provides considerably stronger assurance than digest pinning alone, since it confirms not just that the content is exactly what was previously seen, but that it was genuinely produced by the entity it claims to come from in the first place.
Automated tooling for keeping pinned digests current
Because a digest-pinned base image never automatically incorporates upstream updates, automated dependency update tools that specifically support Docker image references can detect when a pinned base image's underlying tag has moved to a new digest and propose an update through the normal pull request review process:
{
"datasource": "docker",
"depName": "node",
"currentDigest": "sha256:3f29a8c1...",
"currentValue": "20"
}
packageRules:
- matchDatasources: ["docker"]
pinDigests: true
This combination, Renovate or a similar tool configured specifically to track and propose digest updates for pinned base images, provides the same stability-with-currency balance described for dependency pinning generally, but applied specifically to the base image reference, which would otherwise require entirely manual tracking.
Differentiating CI and local development pinning strategies
A project's CI pipeline benefits most from strict digest pinning, since reproducibility and certainty about exactly what was tested matters considerably more there than developer convenience; a local development setup might reasonably tolerate a looser tag reference for the convenience of automatically picking up routine updates without needing to manually bump a digest reference on every developer's machine individually:
ARG BASE_IMAGE=node:20
FROM ${BASE_IMAGE}
docker build --build-arg BASE_IMAGE=node:20@sha256:3f29a8c1... -t my-api .
Parameterizing the base image reference through a build argument allows CI to explicitly pin to a verified digest while local development can use a more convenient, looser default, without maintaining two separate Dockerfiles for what is otherwise an identical build process.
Pinning intermediate, build-stage base images separately from the final stage
In a multi-stage build, the build stage's base image and the final stage's base image are independent references, and they can, and often should, be pinned with different levels of strictness reflecting their different actual risk profiles: the build stage's content never ships in the final image at all, while the final stage's base image content is exactly what ends up running in production:
FROM golang:1.22 AS build
FROM gcr.io/distroless/static-debian12@sha256:abc123...
Applying the most rigorous pinning and verification specifically to the final, shipping stage's base image, while being more relaxed about the build-only stage's reference, focuses the actual security and reproducibility effort where it provides the most genuine value.
Confirming a pinned digest still resolves correctly
Because registries can, in rare cases, remove or reorganize content, periodically confirming a pinned digest still successfully resolves avoids discovering a broken reference only at the moment a build is actually needed, often during an urgent deployment or incident response when that discovery is least convenient:
docker pull node:20@sha256:3f29a8c1d8e2b4f6a9c7d5e8b1f3a6c9d2e5f8b1a4c7d0e3f6a9c2d5e8b1f4a7
A scheduled, routine check that every pinned digest reference across active Dockerfiles still resolves successfully catches this rare but genuinely disruptive failure mode proactively.
Common mistakes
- Pinning to an individual platform-specific digest rather than a manifest list's own top-level digest, breaking multi-architecture build support entirely.
- Treating digest pinning as a complete provenance guarantee, without also verifying image signatures for genuinely strong assurance about an image's actual source.
- Applying identical, maximally strict pinning to every environment, including local development, where the resulting friction may not be worth the marginal benefit compared to CI specifically.
- Pinning a multi-stage build's build-only stage with the same rigor as the final, shipping stage, spending verification effort where it provides comparatively little actual value.
- Never verifying that pinned digests still resolve successfully over time, risking discovering a broken reference only during an urgent, time-sensitive build.
Base version pinning extends well beyond the basic tag-versus-digest decision, requiring attention to multi-architecture manifest list digests specifically, complementing digest pinning with signature verification for genuine provenance assurance, and applying differentiated pinning rigor across CI, local development, and multi-stage build phases based on where the actual risk and value genuinely lie.