Docker Registry

Learn how Docker registries store images: tagging, pushing and pulling, Docker Hub, private registries, authentication, and tag strategy.

A registry is a server that stores and distributes Docker images. When you run docker pull or docker push, you are talking to a registry. Registries are how images move from a developer's laptop or CI pipeline to staging and production, so understanding naming, authentication, and tagging is a core operational skill.

Registries and Repositories

  • A registry hosts many repositories (Docker Hub, GitHub Container Registry, Amazon ECR, Google Artifact Registry, Azure Container Registry, or a self-hosted registry).
  • A repository holds versions of one image, identified by tags.
  • A tag is a label for a specific image version.

A full image reference has this form:

[registry-host[:port]/][namespace/]repository[:tag | @digest]

docker.io/library/nginx:1.27                  # official image on Docker Hub
ghcr.io/myorg/my-app:1.4.2                    # GitHub Container Registry
registry.example.com:5000/team/payments:2.0   # private registry

If no registry host is given, Docker uses Docker Hub (docker.io). If no tag is given, it uses latest.

Pull, Tag, Push

# Pull an image
docker pull postgres:16

# Authenticate (you will be prompted for the password or token)
docker login
docker login ghcr.io -u myuser

# Build and name the image for your repository
docker build -t myuser/my-app:1.0.0 .

# Add another tag to the same image
docker tag myuser/my-app:1.0.0 myuser/my-app:1.0
docker tag myuser/my-app:1.0.0 myuser/my-app:latest

# Push
docker push myuser/my-app:1.0.0
docker push myuser/my-app:1.0
docker push myuser/my-app:latest

docker logout

All three tags above point to the same image ID. Pushing uploads only layers the registry does not already have.

For automation, pass tokens through standard input instead of the command line:

echo "$REGISTRY_TOKEN" | docker login ghcr.io -u myuser --password-stdin

Running a Private Registry

The open-source registry image provides a minimal self-hosted registry:

docker run -d --name registry \
  -p 5000:5000 \
  -v registry-data:/var/lib/registry \
  --restart unless-stopped \
  registry:2

docker tag my-app:1.0 localhost:5000/my-app:1.0
docker push localhost:5000/my-app:1.0

curl http://localhost:5000/v2/_catalog
# {"repositories":["my-app"]}

localhost registries work over plain HTTP. For any other host you need TLS, and you should add authentication (for example basic authentication behind a reverse proxy), otherwise anyone who reaches the port can pull or push images.

Tagging Strategy

Strategy Example Notes
Semantic version 1.4.2, 1.4, 1 Human-readable releases; point 1.4 at the latest patch
Git commit SHA a1b2c3d Immutable traceability from running container to source
Build number build-482 Easy to correlate with CI runs
Environment label staging, prod Moves between images, so avoid it for deploys
latest latest Only a default tag name; avoid in production

A common approach is to push both an immutable tag (commit SHA or version) and a moving convenience tag, and to deploy using only the immutable one.

Digests

A digest identifies exact content and cannot be re-pointed:

docker pull nginx:1.27
docker image inspect nginx:1.27 --format '{{index .RepoDigests 0}}'
# nginx@sha256:3c4f...

docker pull nginx@sha256:3c4f...

Deploying by digest guarantees the identical image is used everywhere.

Registry Operations in CI

A typical pipeline step:

IMAGE=ghcr.io/myorg/my-app
TAG=$(git rev-parse --short HEAD)

docker build -t $IMAGE:$TAG .
echo "$GITHUB_TOKEN" | docker login ghcr.io -u "$GITHUB_ACTOR" --password-stdin
docker push $IMAGE:$TAG

Docker Hub and cloud registries also offer image scanning, retention policies, and access control per repository, which are useful in production.

Multi-Architecture Images

If you build on an Apple Silicon (arm64) machine and deploy to amd64 servers, an arm64-only image will fail to run there. Build for the target platform with Buildx:

docker buildx build --platform linux/amd64,linux/arm64 \
  -t myuser/my-app:1.0.0 --push .

The registry stores a manifest list, and each client pulls the variant matching its architecture.

Common Mistakes

  • Deploying latest. You cannot tell which version is running, and rollbacks are ambiguous.
  • Pushing secrets in images. Anyone with pull access can extract them from layers.
  • Making a private registry public or unauthenticated. Without TLS and authentication it exposes your images.
  • Passing passwords with -p on the command line. They end up in shell history and process lists; use --password-stdin.
  • Ignoring architecture mismatches. An image built for arm64 fails on amd64 hosts with an exec format error.

Best Practices

  • Tag every release with an immutable identifier (version or commit SHA) and deploy by that tag or digest.
  • Use access tokens with minimal scope for CI, not personal passwords.
  • Enable vulnerability scanning and retention policies on your registry.
  • Keep private registries behind TLS and authentication.
  • Clean up old tags to control storage costs.

Interview Questions

1. What is a Docker registry?

A server that stores and serves Docker images, organized into repositories with tags. Examples are Docker Hub, GitHub Container Registry, cloud provider registries, and the self-hosted registry:2.

2. What is the difference between a registry and a repository?

A registry is the service that hosts images; a repository is a collection of versions (tags) of one image within that registry, such as myorg/my-app.

3. How do you push an image to a registry?

Authenticate with docker login, tag the image with the registry and repository name (docker tag my-app:1.0 myuser/my-app:1.0), then run docker push myuser/my-app:1.0.

4. Why is the latest tag discouraged in production?

It is a mutable, default tag that does not mean "newest" by itself. Different hosts may pull different content over time, making deployments unreproducible and rollbacks unclear. Use explicit versions or digests.

5. What is the difference between a tag and a digest?

A tag is a mutable label that can be moved to another image. A digest is the SHA-256 hash of the image manifest, so it is immutable and identifies exact content.

6. How would you run a private registry?

Run the registry:2 image with a persistent volume and publish port 5000, then add TLS and authentication. Alternatively, use a managed service such as ECR, ACR, Artifact Registry, or GitHub Container Registry.

Summary

  • Registries store and distribute images; names follow [registry/][namespace/]repository[:tag].
  • Use docker login, docker tag, and docker push to publish; use --password-stdin for credentials.
  • Deploy using immutable tags or digests, not latest.
  • Secure private registries with TLS and authentication, and build multi-architecture images when targets differ.

Continue Learning

Previous: Docker Image Optimization | Next: Docker Troubleshooting

Was this guide helpful?

CodeWithVenu is free to read, with no paywall. If this guide saved you time or helped you prepare, a small voluntary contribution helps me write more practical tutorials, architecture guides, and interview-prep content.