Container Registries

[!NOTE] This module explores the core principles of Container Registries, deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.

1. The Supply Chain

Once you’ve built an image, it lives on your laptop. To share it, you push it to a Registry.

The “App Store” Analogy

Think of a Registry as the App Store for your containers. Just as developers push their apps to the Apple App Store for users to download, you push your Docker images to a Registry for your servers to pull and run.

Hierarchy

  1. Registry: The server hosting images (e.g., docker.io, gcr.io, ecr.aws). This is the entire App Store.
  2. Repository: A bucket for a specific app (e.g., library/ubuntu, my-company/payment-service). This is the specific app page (like the Spotify app page).
  3. Tag: A pointer to a specific version (e.g., 22.04, latest). This is the version number of the app you are downloading.
#  Registry      Repository      Tag
#     ↓              ↓            ↓
docker pull docker.io/library/ubuntu:22.04

2. The Danger of Mutable Tags

Tags are mutable. Anyone with write access can overwrite a tag.

  • Monday: You push code (Commit A) → Tag as v1.
  • Tuesday: You fix a bug (Commit B) → Force push over v1.

This breaks reproducibility. If you deploy v1 on Monday and scale up on Tuesday, your new replicas run different code than your old ones.

War Story: The Silent Deployment Failure

Imagine a scenario where a team uses :latest for their production microservices. A junior developer accidentally pushes an experimental build of the payment service, tagging it as :latest. The auto-scaling system kicks in due to high traffic, pulling the new :latest image for the newly spun-up nodes. Half of the production servers are now running experimental code, causing intermittent checkout failures. This is the danger of mutable tags in a dynamic environment.

The latest Trap

The latest tag is just a default string. It has no semantic meaning. It does not automatically mean “most recent”. It just means “the last thing that was tagged ‘latest’”.

[!WARNING] Production Rule: Never use :latest in production. Always pin to a specific version (v1.2.3) or, ideally, a Digest.


3. Interactive: The Moving Target

Visualize how latest shifts over time, breaking consistency.

Tag Mutability Simulator

V1
SHA: a1b2...
V2
SHA: c3d4...
latest
System State: Running V1 (a1b2...)

4. Immutable Digests

The only way to guarantee you get the exact same bytes is to pull by Digest.

docker pull ubuntu@sha256:2b740602...

A digest is a SHA256 hash of the image manifest. If even one bit changes in the image, the digest changes completely.

5. Image Security

Before you push to a registry, you should scan your image for CVEs (Common Vulnerabilities and Exposures).

Tools

  1. Trivy: Comprehensive, fast scanner.
  2. Docker Scout: Integrated into Docker Desktop.
  3. Clair: Used by Quay.io.
# Example Trivy scan
$ trivy image my-app:latest

HIGH: CVE-2023-1234 (openssl)
Fixed Version: 1.1.1t

6. Private Registries

Most companies use private registries.

  • AWS: ECR (Elastic Container Registry)
  • GCP: GCR / Artifact Registry
  • Azure: ACR
  • Self-Hosted: Harbor

To use them, you must authenticate:

aws ecr get-login-password | docker login --username AWS --password-stdin ...

7. Summary

  1. Tags are Mutable: Don’t trust them for reproducible builds.
  2. Digests are Immutable: Use them for high-security deployments.
  3. Scan Everything: Don’t ship known vulnerabilities.