Registries, Docker Hub, Private Registries, Authentication, Credential Stores, Push/Pull, and Distribution: Diagnostics, Failure Modes, Security, and Performance
Diagnose registry failures from first evidence instead of weakening security: distinguish name/TLS/auth/scope/policy/digest/storage failures, preserve push/pull output and registry logs, and repair the narrow causal layer.
Learning objectives
- Apply an evidence-first sequence that separates DNS/network, TLS, authentication, authorization, reference/digest, registry policy/storage, and consumer pull/deployment state.
- Diagnose command-line password exposure, x509 failures, wrong token scope, moved tags, and missing manifests without hiding the original cause.
- Explain why raw debug traces, broad credentials, insecure registries, backend file deletion, and blind restarts are unsafe shortcuts.
- Interpret registry logs/API status and shared-blob behavior before changing storage or retention.
- Perform a bounded intentionally broken pull and repair only the repository/reference layer.
1. Evidence-first diagnostic sequence
- Preserve the exact failing command, timestamp, registry reference, status/error, push/pull digest output, and relevant logs.
-
Confirm Docker host/platform,
docker version,docker info, anddocker context show. - Confirm daemon/API availability before blaming the registry.
- Confirm the exact source/build/image digest you intended to publish or retrieve.
- Inspect local image/container state if the symptom appears after pull.
- Inspect registry DNS/TLS/network reachability.
- Inspect authentication and repository authorization separately.
- Inspect registry content/policy/storage only after identity and transport are proven.
- Apply the smallest reversible correction and rerun only the failed scope.
2. Failure map: classify the layer before changing anything
| Symptom | Likely layer | Preserve | Do not jump to |
|---|---|---|---|
no such host / connection refused |
DNS/network/listener | Reference, resolver result, endpoint/port, registry container state | Credential reset or image rebuild. |
| x509 unknown authority / hostname mismatch | TLS endpoint trust | Certificate chain, hostname, daemon platform/trust path | insecure-registry as a blanket fix. |
unauthorized / 401 |
Authentication challenge or missing credential | Challenge header, registry hostname, login method; redact tokens | Changing repository names blindly. |
denied / 403 |
Authorization/scope/policy | Principal, repository, requested action/scope | Rotating TLS certificates. |
manifest unknown |
Reference/tag/digest or retention | Exact repository/tag/digest and registry API response | Rebuilding the image immediately. |
| Push succeeds, consumer stays old | Consumer reference/pull/deploy state | Push digest, tag resolution, consumer RepoDigest, container image | Restarting registry. |
| Disk pressure in registry | Retention/storage/GC | Referenced manifests, backend metrics, GC dry-run evidence | Deleting blob files directly. |
3. Intentionally broken example: password on the command line
The following is intentionally wrong and should not be executed with a real credential:
# WRONG: secret can land in shell history / process inspection
docker login registry.example.com -u ci-publisher -p REAL_SECRET
The correction changes only credential delivery:
printf '%s\n' "$REGISTRY_PASSWORD" \
| docker login registry.example.com \
--username ci-publisher --password-stdin
Then verify that logs do not echo the variable and that the configured helper/store owns persistence. This fixes secret exposure; it does not grant missing repository permissions.
4. Intentionally broken example: certificate failure is not an invitation to disable trust
If push returns an x509 trust error, preserve the exact error, registry hostname, certificate SANs, issuing CA, and daemon platform. The repair is normally to present a correct server certificate and place the issuing CA where the Docker daemon expects it for that platform. Docker Desktop, native Linux Engine, rootless Engine, and Windows Engine have different trust locations.
insecure-registry. It
permits unencrypted and/or untrusted registry traffic. Current
Docker documentation explicitly recommends installing the CA instead
for increased security. Use loopback HTTP only as a bounded local
simulation.
5. Authentication success but push denied: inspect token scope
A token can authenticate correctly and still lack
push for team/app. In a Distribution token
flow, preserve the WWW-Authenticate challenge without
copying secret tokens. Check the requested repository and action
scope. If pull works but push fails, that asymmetry is useful
evidence.
Repair authorization at the registry/provider policy layer. Do not grant a broader organization-wide credential merely because one repository scope is wrong.
6. Overwriting a tag without recording the digest destroys release clarity
If stable was pushed twice and only the tag is in the
incident ticket, you may not know which bytes a consumer obtained
earlier. Preserve push logs, registry digest, and consumer
RepoDigest before moving the tag again. The correction is a release
process that records the digest at push/promotion time.
7. Debug logging can become a credential leak
Do not paste raw HTTP traces containing
Authorization: Bearer ..., Basic auth values, cookies,
or signed URLs into tickets/chat. Prefer registry server request
IDs, status codes, repository names, non-secret scopes, and redacted
headers. If a token is accidentally exposed, treat it as compromised
and revoke/rotate according to provider policy.
8. Shared blobs: never delete backend files to fix a single image
Content-addressed blobs can be referenced by many manifests. Direct filesystem/object-store deletion bypasses registry reference knowledge and can corrupt several images. Use supported deletion/retention mechanisms and administrator-controlled garbage collection. For CNCF Distribution, current GC guidance recommends read-only/stopped state during collection and offers a dry-run mode.
9. Performance diagnosis: locate transfer, registry, or storage bottlenecks
Push progress shows uncompressed layer size while network transfer is compressed, so the progress bars are not a direct wire-byte meter. Reused blobs can make subsequent pushes dramatically smaller. Diagnose performance using layer reuse, daemon concurrency settings, registry logs, backend latency/throughput, network path, and client/server resource saturation before altering global upload/download concurrency.
10. Safe failure exercise: wrong repository path, then smallest correction
Against the disposable Chapter 14 registry, intentionally request a nonexistent repository by digest-like workflow:
REGISTRY=127.0.0.1:5000
docker pull "$REGISTRY/devops-academy/does-not-exist:1.0.0" \
2>&1 | tee "$EVIDENCE/expected-manifest-unknown.log" || true
docker logs da-ch14-registry 2>&1 | tail -n 60 \
| tee "$EVIDENCE/registry-after-bad-pull.log"
Interpret the error first. The registry is reachable; the path is simply absent. The repair is to use the intended repository/reference — not restart Docker, not disable TLS, and not prune images.
11. Recovery checklist
- Exact intended digest resolves from the intended repository.
- TLS/auth assumptions match the environment.
- Publisher credential scope is no broader than needed.
- Consumer pull/deployment state is verified independently.
- First-failure evidence remains retained.
- No unrelated registry content, cache, volumes, or daemon configuration were deleted.
Knowledge check
An x509 error occurs during push. What is the safe first correction direction?
Verify hostname/certificate chain and install the correct issuing CA in the Docker daemon’s platform-specific trust location; do not broadly disable verification.
Pull works but push receives denied. What does
that suggest?
Authentication can be valid while the token/account lacks push authorization for that repository scope.
Why is raw HTTP debug output dangerous in a registry incident?
It can contain Authorization headers, bearer tokens, signed URLs, cookies, or other credentials.
Why should registry backend blobs not be deleted directly?
The registry owns references among manifests and shared blobs. Direct deletion can corrupt multiple images and bypass supported retention/GC logic.
A nonexistent repository returns manifest unknown.
Should you restart Docker?
No. Reachability is already proven. Correct the repository/reference or publish the expected manifest; preserve the error as causal evidence.
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.