Docker Registry
- A Docker Registry is a service that stores and distributes Docker images. It’s the central repository from which images are pulled and to which they are pushed.
- Images are identified as
[registry-host/][namespace/]name[:tag] - Default registry: Docker Hub (
docker.io). If no registry is specified in an image name, Docker Hub is assumed.
Public vs Private Registries
Section titled “Public vs Private Registries”| Registry | Provider | Type | Notes |
|---|---|---|---|
| Docker Hub | Docker Inc | Public/Private | Default. Free tier has pull rate limits. |
| GitHub Container Registry (GHCR) | GitHub | Public/Private | Integrated with GitHub Actions. |
| Azure Container Registry (ACR) | Microsoft | Private | Native AKS/Azure integration. Geo-replication. |
| AWS ECR | Amazon | Private | Native ECS/EKS integration. IAM auth. |
| Google Artifact Registry | Private | Replaced GCR. Multi-format (Docker, npm, Maven). | |
| Harbor | CNCF | Self-hosted | Open-source. Vulnerability scanning, RBAC. |
| Nexus Repository | Sonatype | Self-hosted | Multi-format proxy and private registry. |
Working with Registries
Section titled “Working with Registries”# Login to Docker Hubdocker login# ⚠️ Credentials are stored as base64 in ~/.docker/config.json — not encrypted.# Use a credential helper (docker-credential-pass, docker-credential-osxkeychain)# to store them securely. See: docker help login
# Login to a private registrydocker login myregistry.azurecr.io
# Pull an image from Docker Hub (implicit registry)docker pull nginx:alpine
# Pull from a private registry (must be logged in)docker pull myregistry.azurecr.io/apps/my-app:v1.2
# Tag an existing local image for a registrydocker tag my-app:latest myregistry.azurecr.io/team/my-app:v1.2
# Push to registrydocker push myregistry.azurecr.io/team/my-app:v1.2
# List images in a registry (Docker Hub example via API)curl -s https://hub.docker.com/v2/repositories/library/nginx/tags | jq '.results[].name'
# Logoutdocker logout myregistry.azurecr.ioRunning a Private Registry
Section titled “Running a Private Registry”Docker distributes an official registry image you can self-host:
# Run a local registry on port 5000docker run -d \ -p 5000:5000 \ --name registry \ --restart=always \ -v registry-data:/var/lib/registry \ # persist images registry:2
# Push an image to your local registrydocker tag my-app:latest localhost:5000/my-app:latestdocker push localhost:5000/my-app:latest
# Pull from your local registrydocker pull localhost:5000/my-app:latestFor a production private registry, add:
- TLS: Use a reverse proxy (Nginx, Caddy) with a valid certificate. Docker requires HTTPS for non-localhost registries.
- Authentication: Basic auth via htpasswd file, or proxy through an OAuth provider.
- Vulnerability scanning: Use Harbor or Trivy integration.
Image Naming Deep Dive
Section titled “Image Naming Deep Dive”| Image Reference | Resolved To |
|---|---|
nginx | docker.io/library/nginx:latest |
nginx:alpine | docker.io/library/nginx:alpine |
myuser/myapp | docker.io/myuser/myapp:latest |
myregistry.io/myapp:v2 | myregistry.io/myapp:v2 |
myapp@sha256:abc123 | Content-addressed, exact digest |
- Digest pinning:
sha256:...digests are immutable. Unlike tags, they cannot be overwritten. Use digests in production for reproducible deployments. - Tags are mutable. The image behind
nginx:latestchanges every time a new release is published. Never rely onlatestin CI/CD. - Content Trust: Set
DOCKER_CONTENT_TRUST=1to enforce that only cryptographically signed images are pulled. Requires the image publisher to sign with Docker Notary. Not widely adopted outside official images, but useful in high-security environments.
Docker Hub Rate Limits
Section titled “Docker Hub Rate Limits”- Unauthenticated pulls: 100 pulls per 6 hours per IP.
- Authenticated free tier: 200 pulls per 6 hours per account.
- Paid plans: unlimited.
For CI/CD pipelines that frequently pull from Docker Hub, either:
- Authenticate your CI runner with a Docker Hub account.
- Mirror Docker Hub through a private registry (pull-through cache) to avoid rate limits hitting your entire team.
# Configure a Docker Hub pull-through mirror in /etc/docker/daemon.jsoncat > /etc/docker/daemon.json <<'EOF'{ "registry-mirrors": ["https://my-dockerhub-mirror.mycompany.io"]}EOF
# Restart Docker for the change to take effectsystemctl restart docker