Chapter 13Lesson 03~100 minutes

Image Tags, Digests, Mutable vs Immutable References, Pull Policies, Pinning, and Reproducibility: Configuration, Design Choices, and Tradeoffs

Choose tag, digest, pull-policy, and promotion strategies deliberately. This lesson compares floating development tags, semantic release aliases, digest pinning, base-image pins, Docker and Compose pull policies, and build-once/promote-the-same-digest workflows.

Pull policyPinningPromotionReproducibilityTradeoffs

Learning objectives

  • Select when human-friendly tags, digest pins, or both should appear in build and deployment configuration.
  • Compare Docker Engine and Compose pull policies as freshness controls rather than identity controls.
  • Explain the operational tradeoff of base-image pinning: reproducibility improves, but updates must become an explicit reviewed event.
  • Design a build-once/promotion workflow that moves aliases without rebuilding approved release bytes.
  • Choose development and production policies from evidence, trust boundary, rollback, and offline requirements.

1. Start with the decision, not the syntax

The right reference strategy depends on what the consumer is trying to optimize. A developer may intentionally follow app:dev. A production rollback procedure needs an exact immutable identity. A Dockerfile base should usually be readable to humans but also reproducible enough to audit. These goals are not contradictory when you keep an alias and its digest together.

2. Reference strategy decision table

Pattern Strength Risk Good fit
app:dev Simple, intentionally follows a moving channel. Same config can resolve to new content later. Fast inner-loop development.
app:3.8.0 Readable release intent. Still mutable unless registry policy protects it. Catalog/UI alias plus recorded digest.
app@sha256:… Exact immutable registry object. Less readable; updates require explicit change. Production deployment, rollback, evidence.
app:3.8.0@sha256:… Readable intent plus immutable constraint. Must keep tag/digest pairing current. Dockerfile base pinning and reviewable config.

3. Docker Engine pull policies

docker run --pull=missing uses local cached content when the named image exists, always initiates a pull before container creation, and never requires the image to already be local. These policies answer “should I consult the registry?” They do not answer “which release is approved?”

Policy Registry behavior Typical use Identity warning
missing Pull only if not local. General local use; offline-tolerant cache. A mutable tag may remain stale locally.
always Pull before creation. Follow a mutable channel deliberately. Fresh tag resolution is still mutable.
never No implicit pull. Offline or tightly staged hosts. You must prove the preloaded content identity separately.

4. Compose adds time-based and build-aware policies

Current Compose service configuration supports always, never, missing, build, daily, weekly, and every_<duration>. The latest tag is always pulled under missing. This is useful for developer freshness policies, but production identity should still be explicit.

services:
  api:
    image: registry.example/team/api@sha256:REVIEWED_DIGEST
    pull_policy: missing

Here the digest fixes identity; the policy controls whether missing content can be retrieved. Avoid inventing a tag-refresh policy as a substitute for release approval.

5. Base-image pinning: deterministic input versus automatic drift

Docker’s build guidance recommends digest pinning when you need exact base identity. A pattern such as FROM alpine:3.21@sha256:… communicates the intended release line and freezes the exact object. If the publisher later updates 3.21, your build does not silently change.

The cost is deliberate maintenance: a pinned base does not automatically absorb security fixes. Use dependency automation or scheduled review to propose a new digest, rerun tests/scans, and merge the update with an audit trail.

6. Build once; move references, not bytes

Controlled promotion path
flowchart TD
  A[Source SHA] --> B[Build once]
  B --> C[Digest D]
  C --> D[Test / scan / attest D]
  D --> E[Attach candidate alias to D]
  E --> F[Promote staging alias to D]
  F --> G[Promote production alias to D]
  G --> H[Deployment records D]
            

If promotion rebuilds the source, the new result is a new artifact that requires its own evidence. A tag that says the same version does not make two builds identical.

7. Multi-platform promotion needs two levels of identity

For a multi-platform release, record the index digest as the release-set identity and retain the child manifest digests used by supported platforms. If an arm64-only incident occurs, the index proves the overall release while the arm64 descriptor identifies the exact failing platform artifact.

8. Worked scenarios

Scenario Recommended pattern Why
Developer follows newest integration build Floating :dev + --pull=always Freshness is intentional; failures are expected to track the channel.
Air-gapped validation host Preloaded digest + --pull=never No network lookup; exact preload evidence is required.
Production release Deploy approved repo@digest; optionally publish readable alias Independent verification and rollback.
Dockerfile base tag@digest with scheduled update PRs Readable intent plus deterministic bytes and reviewable upgrades.

9. Registry policy can reinforce—but not replace—evidence

Some registries can protect tags from mutation. That is useful governance, but consumers should still record digests because the digest travels with scans, signatures, attestations, deployment records, and incident evidence. Registry policy answers “who may move this alias?”; the digest answers “what content is this?”

10. Decision challenge

Your CI pipeline pushes app:2.7.4, tests it, then rebuilds the same source in a production job and pushes the new bytes under the same tag. Explain why this breaks provenance even if both images pass tests, and redesign the workflow so staging and production consume the exact approved digest.

Next lesson

Next: Diagnostics, Failure Modes, Security, and Performance

Use these identity distinctions to diagnose stale tags, wrong platforms, pull-policy surprises, and rebuild drift.

Knowledge check

Is pull_policy: always a substitute for digest pinning?

Why can tag@digest be useful in a Dockerfile?

What maintenance burden does digest pinning introduce?

What is wrong with rebuilding during promotion?

For a multi-platform release, why retain child manifest digests?

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.