Git, CI/CD & GitOpsCXII · Container Delivery PipelineRegistryAndDeploy
Registry and deploy — the artefact goes home
What you'll learn
- Push the signed image to a registry by digest and tag it for human consumption without pinning production to the tag
- Land the digest in the rendered manifest (Helm values, Kustomize overlay) so the cluster pulls by digest
- Recognise that promotion between environments is digest promotion, not rebuild
- Roll back by reverting the manifest commit; the registry and the signature remain intact
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
The final stage of the container delivery pipeline takes the signed, attested image and places it where the cluster can find it. The image is pushed to a registry by digest; the digest lands in the rendered manifest; the GitOps controller syncs the cluster. Promotion between environments is digest promotion - the same blob moves from staging to production without a rebuild. Rollback is a manifest revert that keeps the registry entry and the signature intact. The chain from commit to running pod is closed.
The registry as the chain endpoint
The registry is the durable home of the image, the signature, and the attestations. The OCI distribution specification models all three as content-addressed blobs:
flowchart LR
A["Image digest sha256:8a3f..."] --> B["registry.example.com/app@sha256:8a3f..."]
A --> C["Signature"]
A --> D["SBOM attestation"]
A --> E["Vuln report attestation"]
B --> F["Tag app:8a3f9d2 (alias)"]
B --> G["Tag app:v3.2.7 (alias)"]
The push writes the image blob and its attestations under the same digest. The tags are mutable pointers; the digest is the immutable identifier. Two manifests, two environments, one blob: staging and production can reference the same digest without rebuilding.
A registry that is not the cluster’s source of truth breaks the
chain. A workflow that pushes to the registry, then applies
manifests with kubectl apply from the runner, bypasses the
controller and produces a cluster state that the GitOps
controller does not know about. The pipeline must push to the
registry; the GitOps controller must read from the registry and
apply to the cluster.
Pushing the image and landing the digest
The push step:
docker push registry.example.com/app@sha256:$IMAGE_DIGEST
docker tag registry.example.com/app@sha256:$IMAGE_DIGEST \
registry.example.com/app:$COMMIT_SHA
docker push registry.example.com/app:$COMMIT_SHA
The digest push writes the blob; the tag push writes a pointer for humans. Both are recorded in the registry; the digest is the durable identifier.
The render step lands the digest in the manifest. For Helm, the values file:
image:
repository: registry.example.com/app
digest: sha256:8a3f9d2c1e7b6f4a5d9c0e2b1a8f7d6c5b4a3e2d1c0b9a8f7e6d5c4b3a2f1e0d
tag: v3.2.7
For Kustomize, the image transformer in the overlay:
images:
- name: app
digest: sha256:8a3f9d2c1e7b6f4a5d9c0e2b1a8f7d6c5b4a3e2d1c0b9a8f7e6d5c4b3a2f1e0d
Either way, the rendered manifest carries the digest. The GitOps controller reconciles to that manifest; the kubelet pulls that digest. The tag stays as a human-readable alias in the values file but is not what the cluster pulls.
Promotion is digest promotion
The same digest can be promoted from staging to production without rebuilding. The CI job publishes once; the values file or overlay is updated to point to that digest for the next environment:
flowchart LR
A["CI build at commit 8a3f9d2"] --> B["registry.example.com/app@sha256:8a3f..."]
B --> C["overlays/staging (digest 8a3f...)"]
B --> D["overlays/prod (digest 8a3f...)"]
C --> E["Argo CD sync to staging"]
D --> F["Argo CD sync to production"]
Two manifests, two environments, one immutable blob. Rebuilding
per environment defeats the purpose: a staging build at
${COMMIT_SHA} and a production build at the same commit a few
minutes later produce different digests, because build
timestamps and layer metadata move between runs. Promote the
digest, not the build.
Rollback is a manifest revert
The cluster’s rollback path is the GitOps controller’s revert. The manifest that pointed at digest B is reverted to point at digest A; the controller reconciles; the kubelet pulls digest A again. The registry still holds both digests; the signatures still cover both; the attestations still describe both.
git revert --no-edit HEAD~1
git push origin main
The cluster rollback is a Git operation. The image rollback is no operation - the digest has not changed, the blob is still in the registry, the signature is still valid. The cluster’s desired state changes; the registry’s content does not.
A rollback that requires a rebuild is a rollback that has lost the chain. The image that the cluster is rolling back to is a different image than the one it rolled back from; the attestations do not carry forward; the audit trail splits.
What this stage does not do
The registry-and-deploy stage closes the chain. It does not:
- Rebuild the image. The build is a single, per-commit operation; promotion is digest promotion, not rebuild.
- Rotate signing keys. Key rotation is a separate, scheduled operation.
- Trigger the test stage. Tests run earlier in the chain, gated on the source commit.
- Audit past deployments. The attestations on the digest are the audit trail; audits consume them, they do not write them.
Production discipline
- Push by digest, tag for humans. The push writes the digest; the tag is an alias for humans; the manifest keys off the digest.
- Render manifests in CI, not on the runner. The rendered manifest is an artefact that lives in Git; the values file that lands the digest is committed, reviewed, and versioned.
- Promote by digest, not by build. Updating the values file or overlay to point at the existing digest moves the same artefact to the next environment.
- Roll back by reverting the manifest, not by rebuilding. The digest is still in the registry; the signature still covers it; a Git revert restores it.
- Verify in the admission controller on every pull. The signature is metadata until something checks it; the admission controller is the check.
Cross-course references
- This course, Part CXI (KubernetesDelivery) - covers the GitOps sync and reconcile loop on the cluster side.
- This course, Part XLV (ImmutableIdentity) - covers content addressing and digest promotion across environments.
- Container Security for Production Sysadmins - Parts VII-VIII cover admission control, the verifier side of the deploy.
Quiz
Knowledge check · 4 questions
Q1. A team rebuilds the same commit per environment - once for staging, once for production - and references the resulting images by tag. What is the failure mode?
Q2. Rolling back a deployment that references a digest by reverting the manifest commit does not require a rebuild and does not change the registry contents.
Q3. Name the three things that the registry stores under the same digest, and identify which one is the durable identifier the pipeline keys off.
Q4. Diagnose a deployment where the manifest references a tag instead of a digest, and prescribe the fix.
A team deploys a container application. The CI builds, signs, and pushes the image with the tag `registry.example.com/app:v3.2.7`. The values file references `tag: v3.2.7`. The cluster pulls and runs. The team later publishes v3.2.7-hotfix1 under the same tag `v3.2.7` (the team reuses tags across releases). The next sync pulls the new digest under the same tag without a manifest change. Production is running a digest no one reviewed.
Passing score: 75%. Answers are checked in this browser.