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.

๐Ÿค” Sound familiar?
  • 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 manifests

Prod 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.