Docker Registries: Docker Hub, Private & Cloud Registry Guide
A Docker registry stores and distributes container images. Docker Hub is the default public registry, but most production environments use private registries for security, compliance, and performance. Understanding registry operations — authentication, tagging strategies, pull-through caching, garbage collection, and CI/CD integration — is essential for managing containerized applications at scale. This guide covers the full spectrum of registry patterns, from basic Docker Hub usage to production-grade private registry architectures.
Docker Hub
Docker Hub is the default public registry. Every docker pull or docker push goes to Docker Hub unless you specify a different registry.
Pulling and Pushing
# Implicit Docker Hub pull
docker pull nginx:latest
docker pull python:3.12-slim
# Equivalent explicit form
docker pull docker.io/library/nginx:latest
# Push to Docker Hub
docker tag my-app:latest username/my-app:latest
docker login
docker push username/my-app:latestRate Limits and Mitigation Strategies
As of 2024, Docker Hub enforces pull rate limits: anonymous users get 100 pulls per 6 hours per IP, and authenticated free users get 200 pulls per 6 hours. These limits can be restrictive for CI/CD systems and shared development environments. The limits apply to pull requests from Docker Hub’s image registry (docker.io), not to pushes or operations on other registries.
Strategies to mitigate rate limits:
- Authenticate in CI — authenticated users get double the rate
- Use a pull-through cache — cache images on your network after first pull
- Mirror to a private registry — replicate frequently used images
- Use Docker Hub’s Pro/Business tier — higher limits for paying customers
The Docker documentation on rate limits recommends pull-through caching as the most effective mitigation for teams with multiple developers or CI runners.
Running a Private Registry
Docker Registry is distributed as a container image, making it trivially simple to deploy:
# Start a local registry
docker run -d -p 5000:5000 --name registry registry:2
# Push to private registry
docker tag my-app:latest localhost:5000/my-app:latest
docker push localhost:5000/my-app:latest
# Pull from private registry
docker pull localhost:5000/my-app:latestProduction Registry with Authentication
Production registries require authentication and TLS:
# Create password file
mkdir auth
docker run --entrypoint htpasswd httpd:2 -Bbn admin securepassword > auth/htpasswd
# Run registry with auth and TLS
docker run -d -p 5000:5000 \
-v /data/registry:/var/lib/registry \
-v $PWD/auth:/auth \
-v /certs:/certs \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
-e "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt" \
-e "REGISTRY_HTTP_TLS_KEY=/certs/domain.key" \
registry:2The Docker Registry documentation emphasizes that TLS is mandatory for production deployments — without it, all traffic including passwords and image data is transmitted in plaintext.
Pull-Through Cache Configuration
A pull-through cache stores images locally after the first pull, speeding up subsequent pulls and reducing bandwidth:
services:
registry-cache:
image: registry:2
ports:
- "5000:5000"
environment:
REGISTRY_PROXY_REMOTEURL: https://registry-1.docker.io
volumes:
- cache-data:/var/lib/registryConfigure Docker daemon to use the mirror by adding to /etc/docker/daemon.json:
{
"registry-mirrors": ["http://localhost:5000"]
---Image Tagging Strategies
Semantic Versioning
docker build -t my-app:1.0.0 .
docker build -t my-app:1.0 .
docker build -t my-app:1 .
docker build -t my-app:latest .Multiple tags for the same image provide different levels of specificity. Consumers pin to the most specific tag they need: my-app:1.0.0 for exact version pinning, my-app:1 for minor updates. The CNCF’s Tagging Best Practices guide recommends always providing at least two tags per build — a unique identifier and a semantic version.
Git SHA Tagging for Traceability
docker build -t my-app:$(git rev-parse --short HEAD) .Git SHA tagging ensures every image maps precisely to its source commit. In production, you can trace any running container back to its exact source code — essential for debugging and compliance. Organizations subject to SOC 2 or PCI DSS audits typically require SHA-based tagging for auditability.
Combined Production Strategy
docker build \
-t my-app:$(git rev-parse --short HEAD) \
-t my-app:$BUILD_NUMBER \
-t my-app:latest \
.This combination provides traceability (SHA), sequential ordering (build number), and a convenience pointer (latest). Production deployments reference the SHA or build number tag; latest is for development convenience only.
Cloud Registry Services
Amazon ECR
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin \
<account>.dkr.ecr.us-east-1.amazonaws.com
docker push <account>.dkr.ecr.us-east-1.amazonaws.com/my-app:latestGoogle Artifact Registry
gcloud auth configure-docker us-central1-docker.pkg.dev
docker push us-central1-docker.pkg.dev/my-project/my-repo/my-app:latestAzure Container Registry
az acr login --name myregistry
docker push myregistry.azurecr.io/my-app:latestRegistry Management
Listing Images via API
# List repositories
curl http://localhost:5000/v2/_catalog
# List tags for a repository
curl http://localhost:5000/v2/my-app/tags/list
# Get manifest for an image
curl http://localhost:5000/v2/my-app/manifests/latestGarbage Collection
Deleting manifests does not free disk space. Run garbage collection periodically:
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.ymlThe garbage collector removes unreferenced blobs. Run it during maintenance windows because it requires exclusive access to the registry storage.
Registry Replication and Geo-Distribution
For teams operating across multiple regions, registry replication ensures fast image pulls regardless of geographic location. Most cloud registries support automatic replication: Amazon ECR supports cross-Region replication, Google Artifact Registry supports multi-region repositories, and Azure Container Registry supports geo-replication. For self-hosted registries, run multiple registry instances behind a load balancer with shared storage (NFS, S3, or GCS) to distribute pull load.
Replication is particularly valuable for globally distributed Kubernetes clusters. Without it, a cluster in Europe pulling from a registry in the US incurs cross-continental latency on every image pull, adding 200-500ms per layer request. Docker’s registry documentation recommends geo-replication for any deployment spanning more than one continent.
Registry Security Best Practices
Access Control
Implement the principle of least privilege for registry access:
- Pull access — CI/CD systems and production nodes need only pull permission
- Push access — limited to CI/CD pipelines and authorized developers
- Admin access — restricted to the infrastructure team
Image Signing and Provenance
Use Cosign (Sigstore) to sign images:
# Sign an image with Cosign
cosign sign --key cosign.key registry.example.com/my-app:v1.0.0
# Verify before deployment
cosign verify --key cosign.pub registry.example.com/my-app:v1.0.0Signed images provide cryptographic verification that the image was built and pushed by an authorized party. In CI/CD pipelines, configure admission controllers (like Kyverno or OPA Gatekeeper) to reject unsigned images in production environments.
Retention Policy Automation
Configure automated retention policies to prevent registry storage from growing unbounded. Cloud registries support lifecycle policies that automatically delete images matching criteria — for example, retaining only the last 100 tagged images or deleting images older than 90 days. For self-hosted registries, implement a scheduled cleanup job using the registry API to identify and remove stale tags, followed by garbage collection to reclaim disk space.
Vulnerability Scanning
Integrate scanning into the CI/CD pipeline as a gating step:
# Trivy scanner
trivy image registry.example.com/my-app:v1.0.0 --severity CRITICAL,HIGH
# Docker Scout
docker scout recommendations registry.example.com/my-app:v1.0.0FAQ
What is the difference between a registry and a repository?
A registry is the server that stores images (e.g., Docker Hub, localhost:5000). A repository is a collection of related images within a registry, identified by name (e.g., nginx, my-app). An image is a specific snapshot within a repository, identified by tag (e.g., nginx:latest, my-app:1.0.0).
Should I use immutable tags?
Yes, especially for production. Immutable tags are never overwritten — each build gets a unique tag (SHA, build number, or timestamp). This ensures traceability and prevents the “I deployed latest but which version?” problem. Overwriting tags should be reserved for development environments.
How do I clean up old images from a private registry?
Use the registry API to list tags, delete unused ones, then run garbage collection. For automated cleanup, tools like crane (Google’s container registry tool) and reg support bulk operations. Most cloud registries have built-in lifecycle policies that automatically expire old images.
Can I use a registry as a CI/CD cache?
Yes. Pull the previous image with --cache-from to use it as a build cache source. This technique, called registry-based caching, works across CI runners because the cached layers are stored in the registry rather than on local disk.
How do I scan images in a registry for vulnerabilities?
Most cloud registries provide built-in scanning (Amazon ECR — Inspector, Google Artifact Registry — Vulnerability Scanning, Docker Hub — Docker Scout). For self-hosted registries, integrate Harbor (which includes Clair or Trivy scanning) or set up a CI pipeline that scans images before push.
Conclusion
Choose a tagging strategy that provides traceability from running container to source code. Use immutable tags for production — never overwrite a production tag. Set up a pull-through cache to mitigate rate limits and speed up pulls. Scan images before pushing to production registries. For most teams, a cloud registry (ECR, GAR, ACR) provides the best balance of features, security, and maintenance overhead. For more on container build and deployment, see our Docker CI/CD integration guide and Docker multi-stage builds.
Running a Private Docker Registry
A private Docker registry stores and distributes images within your organization. Deploy with docker run -d -p 5000:5000 --name registry registry:2. Configure TLS with Let’s Encrypt or your CA. Authentication via htpasswd. Garbage collection reclaims space from deleted manifests: docker registry garbage-collect /etc/docker/registry/config.yml. Registry storage backends include filesystem (default), S3, Azure, GCS, and Swift. S3 configuration for cost-effective, scalable storage with encryption. Registry v2 uses content-addressable storage — images are identified by digest. Pull-through cache mirrors Docker Hub, reducing bandwidth and improving speed. Cleanup policies with Harbor or Nexus Repository Manager provide UI-based management.
Security and Compliance
Sign images with Notary or cosign for supply-chain security. Vulnerability scanning with Clair, Trivy, or Anchore integrates with registry webhooks. Rate limiting on registry pulls prevents abuse. Access control via token-based authentication or OIDC integration. Use immutable tags (myapp@sha256:...) in Kubernetes deployments to prevent drift.