Chapter 36Lesson 01~170 minutes

Docker in CI/CD: Reproducible Builds, Buildx, Registry Caching, Ephemeral Runners, and Release Promotion: Concepts, Architecture, and Mental Model

Design CI/CD around exact source revisions, ephemeral trusted builders, scoped caches, immutable image digests, attestations, and promotion of the same bytes instead of release-time rebuilds.

CI/CDImmutable digestsBuildxEphemeral buildersPromotion

Learning objectives

  • Explain why a CI release must be bound to one exact source revision and one immutable image or index digest.
  • Trace source SHA through builder identity, cache scope, image digest, tests, attestations, registry publication, promotion alias, and runtime verification.
  • Distinguish build completion from image publication, test success, attestation creation, promotion, and deployed identity.
  • Explain why ephemeral runners and scoped caches reduce cross-job state leakage without making cache content inherently trustworthy.
  • Define the evidence required to prove that release promotion reused the original bytes instead of rebuilding them.

1. The practical problem: “the pipeline passed” is not an image identity

A CI system can report success while still leaving an ambiguous release. A mutable tag may move after testing. A deployment job may rebuild from the same branch but obtain a newer base image. A shared cache may inject unreviewed state. A release alias may be updated before the registry has the intended index. The cure is to make the immutable digest—not the job name or tag—the release subject.

The operating rule for this chapter is build once, verify that digest, then promote the same digest. If a later stage rebuilds, it has created a new artifact and must repeat the verification chain.

2. Causal model: source revision to runtime identity

A reproducible CI/CD chain has one immutable subject and multiple independently verifiable claims
flowchart TD
  A[Exact source SHA] --> B[Ephemeral trusted builder]
  B --> C[BuildKit graph + scoped cache]
  C --> D[Image/index digest]
  D --> E[Tests + SBOM + provenance]
  E --> F[Registry subject digest]
  F --> G[Promotion alias / environment]
  G --> H[Runtime pull + digest verification]
  D --> I[Evidence packet]
  E --> I
  F --> I
  H --> I
            

The source SHA fixes the repository state. The builder identity and versions describe who/what executed the build. The cache can accelerate execution but must not replace source or base-image identity. The image/index digest names the resulting bytes. Tests and attestations describe properties of that digest. Promotion changes a human-facing alias or environment pointer, not the digest. Runtime verification closes the loop by proving what was actually pulled or started.

3. Separate state domains before automation

State domain Examples Evidence
Source Git commit, dirty-tree state, workflow definition full SHA; clean/dirty status; workflow/run ID
Builder Buildx version, BuildKit worker, driver, platforms docker buildx version; buildx inspect --bootstrap
Inputs Dockerfile, context, base references, secrets IDs source checksum; base digests; secret IDs only, never values
Cache local/registry/GHA backend and scope cache ref/scope; import/export logs; trust domain
Artifact image or multi-platform index registry repository + immutable digest + platforms
Evidence tests, SBOM, provenance, signature if used reports bound to subject digest
Promotion release/environment alias before/after alias target digest
Runtime deployed/pulled object RepoDigest/index digest/container image ID where applicable

4. Tags are routing labels; digests are artifact identity

A branch tag such as main or a release tag such as v2.4.0 is useful for humans and automation, but it is mutable registry metadata. The registry digest is content-addressed. Your promotion record should therefore say “alias X now resolves to digest Y,” not merely “we pushed X.”

5. Buildx and BuildKit in ephemeral CI

Ephemeral runners intentionally discard local daemon and filesystem state after a job. BuildKit solves the performance cost by exporting cache to an explicit backend and importing it on the next run. Current Buildx supports local, inline, registry and GitHub Actions cache backends in common configurations. The cache key/scope is part of the security design: caches shared across forks or unrelated trust domains can become a supply-chain input.

6. Read-only preflight first

set -eu
printf 'context=%s
' "$(docker context show)"
docker version
docker buildx version
docker buildx ls
docker buildx inspect --bootstrap

Record the actual installed versions instead of assuming the course baseline. In 2026-09-22 upstream Buildx 0.37.1 and BuildKit 0.33.0 are current, but Docker Desktop, distro packages, CI images, and managed builders may package different versions.

7. Cache is an optimization input, not release identity

Cache pattern Strength Primary risk
Runner-local fast on persistent trusted runner state disappears on ephemeral runner; cross-job leakage on shared runner
Local exported directory simple/free and auditable path must scope path and lifecycle per trust domain
Registry cache portable across ephemeral runners registry auth, overwrite scope, retention and cache poisoning need policy
GitHub Actions cache convenient hosted CI integration provider limits and scope semantics; provider-specific trust boundary

8. Build, test, publish and promote are different verbs

  • Build: produce an image/index from declared inputs.
  • Test: execute checks against that exact result or a digest-equivalent pull.
  • Publish: store the result under a registry repository and capture its digest.
  • Attest: attach provenance/SBOM claims to the digest.
  • Promote: move a release/environment alias to the already-tested digest.
  • Deploy: pull/run and verify the digest in the target environment.

9. Current attestation behavior matters

BuildKit creates minimal provenance by default for supported registry outputs. SBOM is opt-in. Attestations are attached to an image index and survive when pushed to a registry; loading into a classic local image store can lose or reject them. Docker-maintained GitHub Actions additionally have provider-specific provenance defaults. Never pass secrets through build arguments: provenance may intentionally record build parameters.

10. Multi-platform releases have two digest levels

A multi-platform tag resolves to an image index digest, which in turn references per-platform manifest digests. Promotion normally targets the index digest so all tested platforms move together. If only one platform is promoted, record that narrower subject explicitly.

11. Evidence ledger

Field Example meaning
source_sha exact commit that triggered the build
run_id CI/local simulation execution identity
builder name, driver, Buildx/BuildKit versions
cache_scope backend + namespace/reference + trust domain
subject_digest immutable image/index digest
test_result pass/fail report linked to subject
attestations SBOM/provenance presence and mode
promotion alias before/after digest
runtime pulled/deployed digest verification

12. Safe baseline for this chapter

  • Never publish only latest as release evidence.
  • Never rebuild in a deployment stage and call it promotion.
  • Never share write-capable caches across untrusted forks by default.
  • Never use build arguments for secrets; use BuildKit secret/SSH mounts.
  • Keep runner/builder credentials short-lived and scoped.
  • Delete only exact disposable builders, registry containers and lab directories.

Knowledge check

Why is a release tag insufficient as artifact identity?

What does “build once, promote many” prohibit?

Why can a cache be a security boundary?

Does successful buildx build prove the registry contains the intended digest?

What is the normal promotion subject for a multi-platform image?

Next lesson

Next: Docker in CI/CD: Reproducible Builds, Buildx, Registry Caching, Ephemeral Runners, and Release Promotion: Guided Hands-On Workflow and Core Operations

Continue with the next lesson in the course sequence and carry forward the evidence-first Docker operating model.

Official references and version notes

Verified baseline:

2026-09-22. Upstream Buildx 0.37.1 and BuildKit 0.33.0 are current. Docker’s current cache documentation lists inline/local/registry/GHA backends in common use; minimal provenance remains the BuildKit default on supported image outputs, while SBOM is opt-in.

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
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.