Registries, Docker Hub, Private Registries, Authentication, Credential Stores, Push/Pull, and Distribution: Concepts, Architecture, and Mental Model
A registry is not just a remote folder of image tarballs. This lesson builds the request and trust chain from registry endpoint and repository scope through authentication challenge, manifest and blob transfer, digest verification, local image identity, and policy boundaries.
Learning objectives
- Explain the registry request path from endpoint/TLS through auth challenge, repository scope, manifest/blob transfer, and local image identity.
- Distinguish authentication, authorization, transport trust, artifact identity, and hosted-service policy.
-
Explain Docker credential stores/helpers without treating
base64-encoded
config.jsonvalues as encrypted secrets. - Relate tags, manifests/indexes, blobs, push/pull output, RepoDigests, and local image IDs without collapsing them.
- State why production registries require trusted TLS/access controls while the chapter uses a loopback-only simulation.
1. The problem: distribution crosses more trust boundaries than a local image build
By Chapter 13, an image digest gave you immutable artifact identity. Chapter 14 adds a networked distribution service. The moment an image crosses that boundary, more questions appear: Which registry hostname did the client contact? Which repository did it request? Which credential source was used? What actions was that identity authorized to perform? Did TLS authenticate the endpoint? Which digest did the registry accept or return? Did the destination Engine actually store that content?
A push can succeed while a later deployment still fails because pull authorization, repository scope, retention policy, network reachability, or the consumer's pull policy differs. Likewise, successful authentication means only “the registry knows who you are”; it does not mean the authenticated principal may push to every repository.
2. Mental model: endpoint → auth challenge → repository scope → content transfer → verified local identity
flowchart TD
A[Docker client / Engine registry reference] --> B[TLS connection registry endpoint]
B --> C{Authorization required?}
C -->|yes| D[401 challenge realm + service + scope]
D --> E[credential source helper / store / token flow]
E --> F[Bearer token repository-scoped actions]
C -->|no| G[Distribution API]
F --> G
G --> H[manifest or index tag or digest]
H --> I[config + layer blobs content-addressed]
I --> J[local image store RepoDigest / platform]
J --> K[container created from verified local content]
The registry endpoint owns distribution. The authorization service
may be a separate endpoint. A token scope commonly names a
repository and actions such as pull or
push. Manifests and blobs are transferred by
digest-addressed APIs. Tags remain mutable names; the digest
returned by a successful push is the immutable evidence you carry
forward.
3. State map: what belongs where?
| State | Owner / location | Evidence | Common mistake |
|---|---|---|---|
| Registry hostname | Client reference + DNS/TLS endpoint |
Exact host[:port], certificate chain, registry
response
|
Treating a repository name as if it implied a registry. |
| Repository namespace | Registry |
Reference such as
127.0.0.1:5000/devops-academy/ch14-app
|
Assuming login to a registry grants every repository action. |
| Credentials | Client-side helper/store or short-lived token system | Credential-helper configuration, login method, token scope — never secret bytes |
Printing config.json or auth headers to prove
login.
|
| Tag | Registry repository metadata | Tag name and the digest it resolves to at a timestamp | Treating a successful tag push as immutable evidence. |
| Manifest/index + blobs | Registry content store | Digest, media type, blob existence/reuse | Adding layer sizes as if transfer/storage duplication is guaranteed. |
| Local image identity | Selected Docker Engine | Image ID, RepoDigests, platform |
Assuming registry push automatically updates every consumer. |
4. Authentication, authorization, and trust are separate decisions
Authentication proves or establishes an identity. Authorization determines whether that identity may pull, push, delete, or discover content in a repository. Transport trust establishes that the endpoint is the intended registry and protects traffic in transit. Artifact trust concerns whether you accept the content itself, often based on digest, provenance, signature, policy, or scan evidence.
The common token flow begins with an unauthenticated registry
request. A protected registry returns
401 Unauthorized and a
WWW-Authenticate challenge containing an authorization
realm, service, and scope. The client obtains a Bearer token and
retries. The token can be narrower than the user account: for
example, pull access to one repository without push permission.
5. Credential stores and helpers: do not normalize plaintext config
On Docker Desktop, credentials are stored in the operating system's
native keychain. On standalone Engine/CLI installations, the Docker
CLI can be configured with a default credsStore or
per-registry credHelpers. Without a helper/store,
credentials in config.json are only base64-encoded, not
encrypted. That is weaker and should not be treated as secret
storage.
printf '%s\n' "$REGISTRY_PASSWORD" | docker login registry.example.com --username ci-publisher --password-stdin
--password-stdin avoids placing the password/PAT
directly in the command line where it can be retained in shell
history or process metadata. It does not make the registry, token
scope, credential lifetime, or host itself trustworthy; those remain
separate controls.
6. Distribution transfers content-addressed objects, not one monolithic image file
A push uploads or reuses blobs, then publishes a manifest (or image index) that references those blobs. If the registry already has a layer digest, the client can reuse it rather than upload duplicate bytes. This is why “layer already exists” is expected evidence, not an error. Pull works in the opposite direction: resolve a tag or digest, obtain the manifest/index, then fetch missing content blobs into the local image store.
docker push or returned by registry/manifest
inspection. A local image ID and a registry manifest/index digest
are related identities, not interchangeable values.
7. TLS is the production baseline; loopback HTTP is only a bounded simulation
Docker assumes registries are secure. Production and shared private registries should present a certificate chain trusted by the Docker daemon and should use access controls. Current Docker documentation shows platform-specific trust locations for custom CAs and client certificates. Marking a registry insecure permits plaintext HTTP or untrusted TLS and weakens endpoint authenticity; it is not a universal certificate troubleshooting fix.
This chapter's executable lab binds the registry only to
127.0.0.1 and uses the current loopback development
exception so learners can practice the Distribution workflow without
changing daemon trust. That lab deliberately does not model
production TLS. The lesson records this limitation instead of hiding
it.
8. Docker Hub is one registry service, not “the registry protocol”
Docker Hub adds hosted account, repository, organization, retention, policy, billing, and rate-limit behavior on top of registry distribution. As of 2026-09-21, Docker documents a six-hour pull-rate limit of 100 for unauthenticated users per IPv4 address or IPv6 /64 and 200 for authenticated Personal users; authenticated Pro, Team, and Business users are listed as unlimited subject to fair use. These are service policies, not properties of the OCI Distribution Specification, and they can change.
The mandatory labs therefore use a local registry and do not require a Docker Hub account. Hub appears as a comparison point, not a prerequisite.
9. Tag deletion, manifest deletion, blob retention, and garbage collection are different states
Registries deduplicate blobs by content digest. A blob can be shared by several manifests. Removing one tag or manifest reference does not automatically mean every referenced blob is safe to delete. CNCF Distribution garbage collection marks referenced content and sweeps eligible unreferenced blobs. Current guidance says to make the registry read-only or stop it during garbage collection to avoid deleting content that is being uploaded concurrently.
That makes retention and garbage collection an administrator-owned storage concern. A normal application publisher should not “fix disk usage” by directly deleting files from registry storage.
10. Read-only inspection before any registry change
docker version
docker info
docker context show
docker buildx version
docker compose version
# Existing local identity only; no network mutation
docker image inspect busybox:1.37.0 --format 'ID={{.Id}} RepoDigests={{json .RepoDigests}}' 2>/dev/null || true
# Inspect client-side helper configuration names without printing credentials
CFG="${DOCKER_CONFIG:-$HOME/.docker}/config.json"
if [ -f "$CFG" ]; then
grep -E '"credsStore"|"credHelpers"' "$CFG" || true
fi
The point is not to guarantee a specific helper exists. It is to
record the actual client configuration before a lab creates an
isolated DOCKER_CONFIG.
11. Common misconceptions
- “I logged in, so I can push anywhere.” Authentication and repository authorization are separate.
- “A successful push deploys the new image.” Push changes registry state; consumers still need their own pull/deployment behavior.
- “The tag is the release identity.” Preserve the returned digest.
- “Turning on insecure-registry fixes TLS.” It bypasses a trust control; repair certificates/trust for production.
- “Deleting a tag frees all layers.” Shared blobs may still be referenced and garbage collection is registry-admin state.
Knowledge check
A registry returns 401 with a Bearer challenge.
Does that prove your username/password is wrong?
No. It proves authorization is required. The client must follow the challenge/token flow; the eventual failure could still be missing credentials, invalid identity, or insufficient repository scope.
Why is docker login success not enough to prove a
push should work?
Login authenticates an identity to a registry. Authorization can
still deny push for the target repository.
What immutable value should accompany a human tag in a release record?
The registry manifest or image-index digest returned/resolved for the pushed release, with platform semantics stated when relevant.
Why should a production registry not use the Chapter 14 loopback HTTP pattern?
The lab is a bounded single-host simulation. Shared/production registries need trusted TLS and access controls so the endpoint and traffic are protected.
Does deleting a tag guarantee its layers disappear from registry storage?
No. Blobs are content-addressed and can be shared by other manifests; retention/garbage collection determines when unreferenced content is removed.
Official references and version notes
-
docker login— authentication,--password-stdin, Docker Desktop native keychains,credsStore, and per-registrycredHelpers. -
docker image push— repository naming, layer reuse, push progress, and digest output. -
docker image pull— pull-by-tag versus pull-by-digest and registry-qualified references. - Registry certificates — platform-specific CA/client-certificate configuration and TLS verification.
- Docker daemon: insecure registries — why plaintext/untrusted registries are testing-only and why trusted CA configuration is preferred.
- Docker Hub pull usage and limits — current rate-limit behavior and authentication attribution.
- CNCF Distribution Registry — current Registry v3 documentation and local-registry workflow.
-
Registry v2 token authentication
—
401challenge, token service, repository scope, Bearer token, and retry flow. - Distribution HTTP API V2 — manifests, blobs, uploads, errors, and digest-addressed operations.
- Deploying Distribution Registry — local development registry, production TLS/auth expectations, and storage.
- Registry garbage collection — shared blobs, reference-aware deletion, mark/sweep behavior, and read-only guidance.
- OCI Distribution Specification v1.1.1 — latest OCI Distribution Specification release used as the standards baseline.
- Distribution Registry v3.1.1 — current stable registry release used as the local-lab baseline.
- Docker Engine 29 release notes — Engine 29.8.1 baseline used when authoring this chapter.
- Buildx releases, BuildKit releases, and Compose releases — current build/orchestration tool release history.
Version-sensitive statements were rechecked against primary documentation on 2026-09-21. The authoring baseline is Docker Engine 29.8.1, Buildx 0.37.1, BuildKit 0.33.0, Dockerfile frontend 1.27.0, Compose 5.5.1, CNCF Distribution Registry 3.1.1, and OCI Distribution Specification 1.1.1. The executable labs still record the versions, context, image digests, registry endpoint, and credential/TLS assumptions actually present. Docker Hub limits and hosted-registry policies are service policy and can change independently of the Docker Engine.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.