1.08 Docker Registry
Overview
A Docker Registry is a centralized storage and distribution system for Docker images. It is the source from which container images are pulled when running containers.
Abstract
Every Docker image must live somewhere before it can be run. That place is a registry β a server-side application that stores and serves image layers. Docker Hub (docker.io) is the default public registry, but cloud providers and self-hosted solutions offer private registries for internal images that should not be publicly accessible.
Why It Matters in Production
Without a registry strategy, teams push images ad hoc, lose track of versions, and risk pulling untrusted or outdated images in production. A well-managed registry ensures:
- Consistent, versioned image delivery across environments
- Access control over who can push or pull images
- A single source of truth for all deployments
Key Concepts
| Concept | Description |
|---|---|
| Registry | The server that stores and serves Docker images (e.g. docker.io, gcr.io) |
| Repository | A named collection of related images within a registry (e.g. library/nginx) |
| Image name format | <registry>/<user-or-account>/<image-name> |
| Official images | Prefixed with library/ on Docker Hub; e.g. nginx β docker.io/library/nginx |
| Tag | A version label on an image (e.g. nginx:1.25, defaults to latest) |
| Private registry | A registry with access controls requiring authentication to push or pull |
Common Use Cases
- Pulling public images from Docker Hub for local development and testing
- Storing internal application images in a private registry (AWS ECR, GCP Artifact Registry, Azure ACR)
- Running a self-hosted registry on-premise using the official
registry:2image - Tagging and pushing images to a local registry for air-gapped environments
Image Naming Convention
Docker image names follow this structure:
<registry>/<account-or-user>/<image-or-repository>
Examples:
docker.io/library/nginx # Official Docker Hub image
gcr.io/kubernetes-e2e-test-images/dnsutils # Google Container Registry
private-registry.io/apps/internal-app # Private registry
When no registry is specified, Docker defaults to docker.io. When no account is specified, it defaults to library (official images).
Example Configuration or Commands
Using a Public Registry (Docker Hub)
# Pull an official image (shorthand β Docker Hub is assumed)
docker run nginx
# Equivalent full image reference
docker run docker.io/library/nginx
Authenticating to a Private Registry
# Log in to a private registry
docker login private-registry.io
# Run a container from the private registry
docker run private-registry.io/apps/internal-app
Credential Storage
By default, Docker stores credentials unencrypted in ~/.docker/config.json. Use a credential helper (e.g. docker-credential-pass or OS keychain) in production to avoid plaintext secrets on disk.
Deploying a Self-Hosted Private Registry
Best Practices
Best Practices
- Always use explicit image tags (e.g.
nginx:1.25.3) β never rely onlatestin production. - Mirror critical public images to a private registry to avoid rate limits and supply chain risks.
- Use a managed registry service (ECR, GCR, ACR) for cloud workloads β they integrate natively with IAM and Kubernetes.
- Automate image pushes through CI/CD pipelines β never push manually from developer machines to production registries.
- Enable image vulnerability scanning in your registry (Trivy, Clair, or built-in cloud scanning).
Security Best Practices
Security
- Always authenticate before pushing or pulling from a private registry β an unauthenticated pull will fail or expose a public image by mistake.
- Never embed registry credentials in Dockerfiles, source code, or CI environment variables without a secrets manager.
- Use TLS for any registry exposed over a network β the self-hosted
registry:2image serves HTTP by default; configure a reverse proxy (nginx/Traefik) with valid certificates. - Apply least-privilege IAM β CI pipelines should have push access; deployments should have pull-only access.
- Rotate registry tokens and service account keys regularly.
- Restrict public access to internal registries using VPC/private networking or firewall rules.
Do and Don't
| β Do | β Don't |
|---|---|
| Use a private registry for all internal images | Push internal images to a public Docker Hub repo |
| Tag images with semantic versions or Git SHAs | Use latest as the only tag in production |
| Log in before pulling from a private registry | Assume Docker will prompt you automatically at runtime |
| Use TLS and authentication on self-hosted registries | Expose a plain HTTP registry on a public network |
| Scan images for CVEs before promoting to production | Deploy images directly from docker pull without validation |
| Use IAM roles for registry access in cloud environments | Store registry passwords in plaintext config files |
Common Mistakes
Common Mistakes
- Forgetting to
docker loginbefore pulling from a private registry β results in an image-not-found error even if the image exists. - Using
latestin production β makes rollbacks and debugging unpredictable. - No TLS on a self-hosted registry β Docker will refuse to push/pull unless the registry is listed as an insecure registry in
/etc/docker/daemon.json. - Not mirroring public images β Docker Hub rate limits unauthenticated pulls (100/6h per IP); CI pipelines will fail unpredictably.
- Pushing to the wrong registry β always verify the full image tag before running
docker push.
Troubleshooting
# Check current login sessions
cat ~/.docker/config.json
# Test connectivity to a self-hosted registry
curl -v https://localhost:5000/v2/
# List images in a local registry
curl http://localhost:5000/v2/_catalog
# Inspect image tags in a repository
curl http://localhost:5000/v2/my-image/tags/list
# Re-authenticate if push/pull fails with 401
docker logout private-registry.io
docker login private-registry.io
# Allow insecure (HTTP) registry β add to /etc/docker/daemon.json
# { "insecure-registries": ["192.168.56.100:5000"] }
# Then restart Docker
sudo systemctl restart docker
Quick Recap
- A Docker registry stores and distributes Docker images
- Docker Hub (
docker.io) is the default public registry;gcr.iois Google's - Image naming follows
<registry>/<account>/<image>β omitting registry defaults to Docker Hub - Private registries require
docker loginbefore pulling or pushing - Deploy a self-hosted registry with
registry:2exposed on port 5000 - Always use TLS, authentication, and image scanning in production registries
Interview / Revision Notes
- What is a Docker registry? A server that stores Docker images and serves them on pull requests.
- What is the default registry? Docker Hub β
docker.io. The default account for official images islibrary. - Full image name for nginx?
docker.io/library/nginx - How do you push to a private registry? Tag the image with the registry URL,
docker login, thendocker push. - How do you deploy a local private registry?
docker run -d -p 5000:5000 --name registry registry:2 - Why avoid
latestin production? It is mutable β the same tag can point to different image content after a new push, making deployments non-deterministic. - Security risk with
~/.docker/config.json? Credentials are stored unencrypted by default; use a credential helper instead.