Chapter 13Lesson 01~95 minutes

Image Tags, Digests, Mutable vs Immutable References, Pull Policies, Pinning, and Reproducibility: Concepts, Architecture, and Mental Model

Tags are convenient release names; digests are content identities. This lesson builds a precise model from repository and mutable tag through registry resolution, manifest or image-index digest, platform-specific content, local image identity, and the container that actually runs.

TagsDigestsImage identityOCI indexEvidence

Learning objectives

  • Explain why a repository tag is a mutable lookup name while a manifest or image-index digest is an immutable content identity.
  • Distinguish registry digest, multi-platform index digest, platform-specific manifest digest, local image ID/config digest, and the image reference stored on a container.
  • Describe how missing, always, and never pull policies change registry lookups without changing the meaning of a digest pin.
  • Design a release evidence chain that preserves a human-friendly alias and the exact digest promoted through environments.
  • Recognize why digest pinning improves reproducibility but still requires an intentional update process for vulnerability remediation.
Chapter 13 principle. A tag answers “what name should humans use?” A digest answers “which immutable registry object did this name resolve to?” Keep both. Tags are excellent navigation; digests are evidence.

1. The problem: the same tag can name different bytes tomorrow

A deployment file that says example/app:stable looks precise, but stable is only a registry tag. A publisher can move that tag from release A to release B without changing the text in your deployment file. If one host already has A cached and another host resolves the registry after the move, the two hosts can run different content while both report the same human-friendly tag.

This is not a Docker bug. Mutable aliases are useful for channels such as stable, 3.4, or nightly. The engineering mistake is treating the alias as immutable evidence. A reliable release process records the digest resolved at the moment of promotion and carries that identity forward with tests, scans, attestations, and deployment records.

2. Mental model: name → resolution → immutable object → platform content

Image reference and identity chain
flowchart TD
  A[repository:tag\nhuman-friendly mutable name] --> B[registry tag resolution]
  B --> C{single or multi-platform?}
  C -->|multi-platform| D[OCI image index\nimmutable digest]
  D --> E[platform manifest\nlinux/amd64 digest]
  D --> F[platform manifest\nlinux/arm64 digest]
  C -->|single-platform| E
  E --> G[config digest + layer digests]
  G --> H[local image object / image ID]
  H --> I[container created from exact local image]
            

The top-level digest may identify an image index. That index can point to several platform-specific manifest digests. A local image ID commonly corresponds to the config object identity for the selected local image. These values can all start with sha256: and still identify different objects.

3. Identity vocabulary: do not collapse these fields

Identity What it identifies Mutable? Operational use
Repository Registry namespace/name, such as registry.example/team/app. The name is stable; its tags can move. Human organization and access policy.
Tag A registry alias such as 1.4.2 or stable. Yes. Discovery, channels, compatibility labels.
Index digest A multi-platform OCI index/manifest list. No for fixed content. Immutable identity of the complete platform set.
Manifest digest One platform-specific image manifest. No for fixed content. Exact platform image identity.
Image ID Local image config identity shown by the Engine. No for that config. Local store/object correlation; not a substitute for registry identity.
RepoDigest A repository-qualified digest association such as repo@sha256:…. The association records immutable content. Audit/pull/run by exact registry identity.

4. Tags are pointers, not content hashes

Adding another tag to a local image does not duplicate its layers. It creates another name for the same local image object. Pushing a tag asks the registry to associate that name with a manifest or index. Pushing different content under the same tag later changes the tag’s resolution.

docker image tag chapter13-a:local example/app:1.0.0
docker image tag chapter13-a:local example/app:stable
docker image inspect chapter13-a:local --format '{{.Id}}'
docker image inspect example/app:stable --format '{{.Id}}'

If both aliases resolve to the same local object, the IDs match. That proves local aliasing only. It does not prove what a remote registry currently returns for either tag.

5. Digest identity and the multi-platform wrinkle

A digest is computed from the serialized content of the object it names. Changing that object changes its digest. For a multi-platform release, the tag commonly points to an image index. The index has one digest; its amd64 and arm64 child manifests have different digests. Therefore, an evidence record should state whether it captured the index digest, a platform manifest digest, or both.

Use registry-aware inspection when the distinction matters:

docker buildx imagetools inspect busybox:1.37.0
docker buildx imagetools inspect busybox:1.37.0 --format '{{.Name}}'

Do not copy a digest from one platform field and describe it as the identity of the entire multi-platform release unless the object being identified is actually the index.

6. Local image ID versus registry digest

The Engine can have a local image before it has ever been pushed, so a local image ID exists without a repository digest. After a successful pull or push, RepoDigests can associate local content with repository-qualified immutable identities. Those are different pieces of evidence.

docker image inspect busybox:1.37.0 \
  --format 'ID={{.Id}} RepoDigests={{json .RepoDigests}}'
Do not audit releases by local image ID alone. A local image ID is useful for correlation on that Engine, but a promotion record needs registry-qualified digest identity so another host can independently resolve the same content.

7. Pull policy changes lookup behavior, not digest immutability

For docker run, --pull=missing is the default, --pull=always performs a registry pull before container creation, and --pull=never forbids an implicit pull. With a floating tag, this determines whether a cached local resolution can be reused. With a digest reference, the identity is already fixed; pulling may fetch missing content, but it cannot silently substitute different content under the same digest.

docker run --rm --pull=missing busybox:1.37.0 true
docker run --rm --pull=always busybox:1.37.0 true
docker run --rm --pull=never busybox:1.37.0 true

Compose has a broader policy surface, including time-based checks. Treat the policy as a freshness/lookup rule, not as artifact identity.

8. Build once, promote the same digest

A release pipeline should bind source revision, build inputs, builder/toolchain, tests, scan/attestation results, and the resulting registry digest. Promotion then attaches an environment-facing alias or deployment reference to that already-tested digest. Rebuilding “the same version” for staging and production creates new bytes and breaks the evidence chain even if the tag text is unchanged.

Human release name

app:3.8.0 or app:stable.

Immutable release identity

registry/team/app@sha256:…, including platform detail when required.

Promotion proof

Evidence that the alias/deployment now references the already-tested digest, not a rebuild.

9. Read-only inspection before changing anything

docker version
docker context show
docker image ls --digests
docker image inspect IMAGE --format \
'ID={{.Id}} RepoTags={{json .RepoTags}} RepoDigests={{json .RepoDigests}} OS={{.Os}} Arch={{.Architecture}}'
docker inspect CONTAINER --format \
'Container={{.Id}} LocalImageID={{.Image}} RequestedImage={{.Config.Image}}'

Capture these fields before pulling, retagging, recreating, or deleting anything during an incident. A later successful pull can erase the evidence that the host had stale content.

10. Common misconceptions

  • “latest means newest.” It is only a conventional tag name.
  • “A semantic version tag cannot move.” Registries generally allow it unless policy prevents it.
  • “The image ID is the registry digest.” They identify different objects/contexts.
  • “Pinned means automatically secure forever.” Pinning freezes bytes; you still need controlled updates when better base images or fixes appear.
  • “Always pull means reproducible.” With a mutable tag, always-pull intentionally asks the registry for the tag’s current meaning.
Next lesson

Next: Guided Hands-On Workflow and Core Operations

Publish two disposable releases, move an alias deliberately, and prove the difference between floating and digest-pinned consumers.

Knowledge check

Can app:stable identify different bytes at two different times?

If a tag points to a multi-platform index, is the index digest necessarily the same as the linux/amd64 manifest digest?

What does --pull=always prove when you run a mutable tag?

Why keep both a semantic version tag and a digest?

Does digest pinning eliminate the need to update vulnerable base images?

Official references and version notes

Version and compatibility note

Version-sensitive statements were rechecked against primary documentation on 2026-09-21. The authoring baseline is Docker Engine 29.8.1, Buildx 0.37.1, BuildKit 0.33.0, and Dockerfile frontend 1.27.0, but every executable lab records the versions and context actually present. Registry tags, platform indexes, local image stores, and Compose behavior can evolve independently; prefer observed digests and current primary documentation over memorized output.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.