Problem Context
A container registry is the boring critical path between your build and your runtime. The wrong choice โ or the wrong configuration โ shows up as failed deploys, surprise egress bills, slow cold starts, and supply-chain CVEs that ship straight to production. The choice is also sticky: image layers, automation, retention policies, and signing all couple deeply.
- Your pull latency spikes during incidents and you don't know why
- You have 4 TB of unused image layers and no retention policy
- You can't answer "is this image signed and scanned?" on demand
The 2026 Landscape
- Azure Container Registry (ACR) โ Azure-native, geo-replication, ACR Tasks for build automation, Trivy-equivalent scanning via Microsoft Defender.
- Amazon ECR โ AWS-native, replication, lifecycle policies, ECR scanning (Inspector).
- GitHub Container Registry (GHCR) โ tight CI/CD integration with Actions, free for public images, signing via Sigstore.
- Google Artifact Registry โ successor to GCR; multi-format (containers, npm, maven), Binary Authorization integration.
- Docker Hub โ fine for OSS, painful rate limits for production pulls without paid plans.
- Self-hosted (Harbor, Zot, Distribution) โ when air-gapped or sovereignty matters.
Picking One (Decision Matrix)
- Same cloud as runtime? Use that cloud's registry โ pulls don't leave the network, no egress charges.
- Multi-cloud or hybrid? GHCR or Harbor centrally + replicate to each runtime cloud.
- Regulated / air-gapped? Harbor or Zot on-prem with mirrored upstream.
- Cost driver? Egress dominates; co-locate registry with runtime.
flowchart LR
CI[GitHub Actions /<br/>Azure DevOps] -->|build + sign| R[(Registry)]
R --> SC[Scan: Trivy / Defender]
SC -->|pass| PR[Policy admit:<br/>signed + scanned]
PR --> K[Kubernetes / ACA / ECS]
R -. replicate .-> R2[(Registry replica<br/>per region)]
Layer Hygiene Is Half the Battle
- Order Dockerfile steps from least- to most-frequently-changed; bust caches as late as possible.
- Use multi-stage builds; ship runtime-only images (no compilers).
- Pick a small base (distroless, alpine, chainguard) โ smaller images pull faster and have fewer CVEs.
- Pin base images by digest (
FROM ubuntu@sha256:...) in production builds.
Tagging Strategy
# Recommended tags per push
sha-3f2a9c8 # immutable, what you actually deploy
2026.05.17-build.412 # human-readable, semver-aware
feature-payments-v2 # PR/branch tags for staging
latest # ONLY for OSS / docs / never in prod manifestsProd manifests reference the digest (image@sha256:...). Mutable tags are convenient and dangerous.
Retention & Garbage Collection
Layer storage grows silently. Lifecycle rules to set on day one:
- Untagged manifests: delete after 7 days.
- Feature/PR tags: delete after 30 days.
- Production digest pins: keep forever (or until you can prove no in-flight rollback target needs them).
- Run garbage collection on a schedule; ACR/ECR offer policy-driven GC.
Supply Chain: Sign, Scan, Verify
- Sign with Sigstore Cosign or Notation. Keyless via OIDC is the default in 2026.
- Scan on push (Trivy, Grype, ECR/ACR managed). Block high/critical on production tags.
- SBOM attached as a referrer (
cosign attach sbom). Required by many enterprise procurement teams. - Verify at admission โ Kyverno or OPA Gatekeeper enforces "only signed, scanned images from approved registries".
Pull Performance
- Geo-replicate to the regions your runtime is in. Cross-region pulls add seconds to cold starts.
- Enable pull-through cache on Kubernetes nodes (containerd
registry mirror). - For very large images, consider lazy-pulling formats (eStargz, SOCI on AWS) โ start before the image is fully pulled.
Failure Modes
- Docker Hub rate limits โ anonymous pulls throttle at 100/6h per IP. Mirror to your own registry.
- Cross-region pulls in prod โ invisible until you scale and the egress bill arrives.
- Mutable tags in prod manifests โ "works on my cluster" mysteries; pin to digest.
- No retention policy โ quietly accumulates terabytes; one day your CI breaks because the registry is full.
Production Checklist
- Registry in the same cloud/region as runtime; geo-replicate for multi-region.
- Sign + scan + SBOM on every push; verify at admission.
- Pin to digest in prod manifests; lifecycle policy for everything else.
- Pull-through cache or mirror for Docker Hub to dodge rate limits.
- Monitor pull latency p95 as an SLI for deploy health.
Key Takeaways
- Co-locate the registry with your runtime; egress and latency are the real costs.
- Sign, scan, SBOM, admission โ supply chain is a four-step pipeline, not a checkbox.
- Lifecycle policies and digest pinning prevent the slow-motion failures registries are infamous for.

