A container registry is a repository for storing and distributing container images, acting as a central hub for your containerized applications.
Let’s walk through setting up a cloud-based container registry, specifically using Google Container Registry (GCR) as an example, which is now largely superseded by Artifact Registry but still relevant for understanding the concepts. The principles apply broadly to AWS ECR, Azure Container Registry, and others.
First, why use a cloud registry? It provides a managed, scalable, and secure place to store your Docker images. Instead of building images locally and manually pushing them to servers, you build them, push them to the registry, and then your deployment tools (like Kubernetes or Cloud Run) pull the latest version from the registry. This decouples building from deployment and enables CI/CD pipelines.
Here’s a typical workflow:
-
Build your Docker image: You write a
Dockerfilethat defines how to build your application’s image.FROM ubuntu:latest RUN apt-get update && apt-get install -y nginx COPY . /var/www/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] -
Tag the image for your registry: Before pushing, you tag the image with the registry’s hostname, your project ID, and a name/tag for the image.
docker build -t my-nginx-app . docker tag my-nginx-app gcr.io/my-gcp-project-id/my-nginx-app:v1.0Here,
gcr.iois the registry hostname,my-gcp-project-idis your Google Cloud project identifier, andmy-nginx-app:v1.0is the repository and tag name. -
Authenticate Docker to your registry: You need to tell your local Docker client how to authenticate with the cloud registry. For GCR, this is often done via
gcloud auth configure-docker.gcloud auth configure-dockerThis command configures the Docker daemon to use your
gcloudcredentials, which often involves a service account or your user credentials. -
Push the image: Now, push the tagged image to your registry.
docker push gcr.io/my-gcp-project-id/my-nginx-app:v1.0The Docker client will upload your image layers to the specified GCR path.
-
Pull the image for deployment: When you deploy your application, your orchestration system will specify the image to pull.
# Example Kubernetes Deployment snippet apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: gcr.io/my-gcp-project-id/my-nginx-app:v1.0 # This is where you reference the registry ports: - containerPort: 80Your Kubernetes cluster (or other deployment environment) will be configured to authenticate with GCR to pull this image.
The most surprising thing about container registries is that they are fundamentally object storage systems, often backed by services like Google Cloud Storage or AWS S3, with an API layer on top that understands Docker image manifest formats and layer relationships. This means the "storage" of your image isn’t a single file; it’s a collection of compressed layers and a manifest that references them.
When you push an image, Docker sends these layers. If a layer already exists in the registry, it’s not re-uploaded. The registry then stores a manifest that describes which layers constitute your specific image tag. Pulling an image involves fetching the manifest and then downloading only the layers that are not already present on the host.
The exact levers you control are primarily:
- Project/Account: Which cloud account or project your registry belongs to.
- Registry Location: The geographical region where your registry data is stored (e.g.,
us-central1,europe-west2). This impacts latency and data residency. - Repository Name: The logical grouping for your images (e.g.,
my-app,backend-services). - Image Tag: A specific version or label for an image (e.g.,
v1.0,latest,staging). - Permissions: Who can push to and pull from your registry. This is managed via IAM roles in cloud providers.
A lesser-known, but mechanically critical, aspect of container registries is how they handle image immutability and garbage collection. While you tag images, the underlying layers are identified by their content hash. When you delete an image tag, the manifest is removed, but the actual image layers might persist in the object storage until a garbage collection process runs. This is crucial for cost management and can be configured at the registry level (e.g., setting retention policies) or triggered manually.
The next concept you’ll likely encounter is implementing automated image building and scanning within your CI/CD pipeline.