Git, CI/CD & GitOpsLIII · Container CIContainer CI
The container supply chain — source to registry
What you'll learn
- Trace every step from a Git commit to a registry tag in a container supply chain
- Identify what each step introduces (trust, content, attestation, risk)
- Distinguish build provenance from runtime provenance
- Recognise why digest pinning is the only contract between CI and a registry
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
A container image is not “the thing docker build produced”. It is
the output of a chain that begins at a commit, passes through a build
step, picks up layers and configuration, is tagged, signed, and
pushed to a registry. Every step in that chain either adds trust or
introduces risk. The job of container CI is to make the trust
explicit and the risk auditable. This lesson walks that chain.
The chain, step by step
Seven steps sit between a commit and a deployable image. They are the same in a GitHub Actions runner, a GitLab runner, or a self-hosted BuildKit cluster:
flowchart LR
A["Git commit"] --> B["Checkout (CI)"]
B --> C["Base image pull"]
C --> D["Layer build (BuildKit)"]
D --> E["Image assembly"]
E --> F["Test and scan"]
F --> G["Tag and push"]
G --> H["Registry (digest)"]
What each step introduces matters more than the order:
- Checkout introduces the exact bytes the build runs against. If the runner checks out the wrong ref, every downstream artifact is wrong; the chain of trust begins here.
- Base image pull introduces the parent. The image you build
inherits every package, certificate, and vulnerability of the
parent. A CVE in
node:20is a CVE in your image. - Build introduces the layers that make up your application: the source code, the dependencies installed, the build cache writes. Build cache is a separate artifact (LIII-02) and a separate risk.
- Assembly introduces configuration: the working directory, the entrypoint, environment defaults, the user the process runs as.
- Test and scan introduces attestation: the SBOM (LIII-05), the vulnerability report, the size budget, the behavioural test results.
- Tag and push introduces the identifier. A tag is mutable; a digest is not. Whether you push by tag, by digest, or both determines what deploys can resolve.
- Registry introduces immutable storage once the digest exists, and access control on who can pull or reference it.
What each step can introduce
The chain is not just a sequence of transformations. It is a sequence of trust boundaries:
| Step | Introduces | Failure mode |
|---|---|---|
| Checkout | Source bytes | Wrong ref checked out |
| Base pull | Parent image | CVE in parent |
| Build | Application layers | Supply-chain compromise |
| Assembly | Runtime config | Privilege escalation |
| Test/scan | Attestations | False negative |
| Tag/push | Identifier | Mutable tag overwritten |
| Registry | Storage | Pull-time substitution |
The two trust boundaries that matter most for the rest of Part LIII are the build step (because it is where most of the compromise surface lives) and the tag/push step (because it is where the digest becomes the contract downstream).
Build provenance versus runtime provenance
The provenance chain starts at the build. Build provenance answers “given this image digest, what build produced it, from what source, on what runner, with what inputs?”. Runtime provenance answers “what is running in production, where did it come from, and was it deployed by something we trust?”. The two halves meet at the attestation: the signed statement that glues the build to the artifact and the artifact to the deployment.
That attestation - whether it is an in-toto/SLSA provenance attestation (LIII-05 and LIII-06), a sigstore signature, or a vendor provenance record - is what makes the chain auditable. Without it, the chain is a sequence of artefacts that happen to share a name.
Production discipline
Five rules that anchor the rest of Part LIII:
- Pin everything by digest where it will be referenced by systems. Tags in source-controlled manifests are bugs waiting to happen; digests are the contract.
- Record what the build consumed. Base image digest, source commit, dependency lockfile - all of these belong in the build provenance and therefore in the attestation.
- Test and scan before the tag is applied. The tag should only land after the tests, scans, and size checks pass. Tagging first and scanning after is how unscanned images end up in production.
- Sign at the registry, not in the runner. The runner can be compromised; the registry signature is what downstream verifiers check (LIII-06).
- Treat the chain as the unit of trust. A signature on an image whose provenance you cannot reconstruct is a signature on nothing.
Cross-course references
- Containerisation for Production Sysadmins - Parts I-IV (Docker foundations) cover the runtime side of the chain (container, image, registry, daemon) that this part consumes.
- Container Security for Production Sysadmins - Parts I-II (image supply chain) cover the threat model; this lesson’s chain is the surface that threat model targets.
Quiz
Knowledge check · 4 questions
Q1. Why is the SHA-256 digest the only safe contract between a CI pipeline and a container registry, when a tag like app:1.4.0 is not?
Q2. A base image pull at the start of a container build introduces the build environment but not any vulnerabilities into the final image.
Q3. Name the two kinds of provenance that together make a container supply chain auditable, and state which one is produced inside the build step.
Q4. Trace a CVE in a third-party base image back to the build chain and identify the missing controls.
A production image built two months ago is suddenly flagged for CVE-2024-9999 in glibc. The team uses app:1.4.0 in their Helm values (no digest pin), a self-hosted BuildKit runner, and an in-toto attestation generated by the runner. The base image is FROM debian:bookworm-slim.
Passing score: 75%. Answers are checked in this browser.