Registries are how images move from your build to servers, CI and teammates.
A registry stores and serves images. Docker Hub (docker.io) is the default; others include GitHub Container Registry (ghcr.io), GitLab's registry, cloud registries (Amazon ECR, Google Artifact Registry, Azure ACR) and self-hosted ones such as Harbor.
The image name says where it goes: ghcr.io/acme/api:1.4.2 means registry ghcr.io, repository acme/api, tag 1.4.2. To push, the local image must carry that name:
docker login ghcr.io
docker tag api:1.4.2 ghcr.io/acme/api:1.4.2
docker push ghcr.io/acme/api:1.4.2Pushes and pulls are layer-based: layers the registry already has, such as your base image's layers, aren't uploaded again.
Authentication: docker login stores credentials in a credential helper (the OS keychain on Desktop) or, failing that, in ~/.docker/config.json. Use access tokens rather than passwords, and short-lived tokens in CI.
Tags vs digests: a tag is mutable; someone can push a different image under 1.4.2 tomorrow. The digest (ghcr.io/acme/api@sha256:...), printed after each push, is the content hash and can never change. Pin digests in production manifests when you need guaranteed reproducibility; tools such as Renovate keep them updated.
Docker Hub limits: anonymous and free-account pulls are rate-limited. CI systems that pull a lot should authenticate, use a pull-through cache or mirror, or pull base images from another registry.
Private repositories require docker login on every machine that pulls them, including servers and CI runners.
Example
echo "$GHCR_TOKEN" | docker login ghcr.io -u my-user --password-stdin
docker build -t ghcr.io/acme/api:1.4.2 -t ghcr.io/acme/api:latest .
docker push ghcr.io/acme/api:1.4.2
# 1.4.2: digest: sha256:7c3e...a1f9 size: 1784
docker push ghcr.io/acme/api:latest # layers already exist: instant
# Pull an exact, immutable image
docker pull ghcr.io/acme/api@sha256:7c3e...a1f9
docker image inspect ghcr.io/acme/api:1.4.2 --format '{{json .RepoDigests}}'
docker logout ghcr.ioRemember
- The registry host is part of the image name; tag images to match before pushing
- Push/pull transfer only missing layers
- Tags can be overwritten; digests are immutable
- Authenticate CI to avoid Docker Hub rate limits
Watch out for
- Passing a password with -p on the command line, where it lands in shell history — use --password-stdin.