Docker Hub and Image Registries
Docker images usually come from a registry: a server that stores image metadata and the layers that make up an image. Docker Hub is the default public registry, but the same ideas apply to private registries from cloud providers, companies, and self-hosted systems. Understanding registries helps you pull the right image, publish your own images, and avoid surprises from changing tags such as latest.
Overview: How registries work
A Docker image is a read-only template built from stacked layers. Each layer is content-addressed, which means Docker identifies it by a cryptographic digest of its contents. A registry stores those layer blobs plus a manifest, which is a small JSON document that says which layers belong to an image, what configuration it has, and, for multi-platform images, which platform-specific manifest should be used.
Docker Hub lives at docker.io and is the registry Docker uses when no registry hostname is written. When you run docker pull nginx:1.27-alpine, the Docker client asks the Docker daemon to fetch an image named docker.io/library/nginx:1.27-alpine. The library namespace is Docker Hub’s special namespace for official images. For normal user or organization images, the name includes the namespace, such as docker.io/acme/api:1.0.0.
Tags are human-friendly pointers to manifests. A tag such as 1.27-alpine may be maintained by the image publisher and can be updated. A digest such as sha256:... identifies exact content. In development, tags are convenient. In production, digests or carefully pinned version tags give better reproducibility because they reduce the risk of deploying different image content with the same name.
Registries do not run containers. They only store and serve image content. Your local Docker Engine pulls layers from the registry into its local image store. When you later run a container, Docker creates a thin writable container layer on top of the read-only image layers and starts the configured process. Removing a container does not remove the image, and deleting an image from your laptop does not delete it from Docker Hub or any remote registry.
Syntax
The common registry workflow is pull, inspect, tag, log in, and push:
docker pull [REGISTRY_HOST/]NAMESPACE/REPOSITORY:TAG
docker image inspect IMAGE[:TAG]
docker tag SOURCE_IMAGE[:TAG] [REGISTRY_HOST/]NAMESPACE/REPOSITORY:TAG
docker login [REGISTRY_HOST]
docker push [REGISTRY_HOST/]NAMESPACE/REPOSITORY:TAG
| Part | Meaning |
|---|---|
REGISTRY_HOST |
The registry server, such as docker.io, ghcr.io, or registry.example.com. If omitted, Docker uses Docker Hub. |
NAMESPACE |
A Docker Hub user or organization, or a project path in another registry. Official Docker Hub images often use the implicit library namespace. |
REPOSITORY |
The image repository name, such as nginx, web-api, or worker. |
TAG |
A movable label pointing to image content, commonly a version like 1.0.0, 1.0.0-alpine, or 2026-08-03. |
docker pull |
Downloads missing manifests and layers into the local image store. |
docker tag |
Adds another local name to the same image ID. It does not copy layers. |
docker login |
Stores credentials so Docker can access private repositories or push to registries. |
docker push |
Uploads missing layers and publishes a tag pointing to a manifest in the remote repository. |
Examples
Pull an image from Docker Hub
docker pull nginx:1.27-alpine
Output:
1.27-alpine: Pulling from library/nginx
Digest: sha256:exampledigestforlessononly
Status: Downloaded newer image for nginx:1.27-alpine
docker.io/library/nginx:1.27-alpine
This pulls the official nginx image from Docker Hub. Because no registry or namespace was provided, Docker expands the name to docker.io/library/nginx:1.27-alpine. If some layers already exist locally because another image shares them, Docker reuses those layers instead of downloading them again.
Inspect the local image reference
docker image inspect --format '{{json .RepoDigests}}' nginx:1.27-alpine
Output:
["nginx@sha256:exampledigestforlessononly"]
A repository digest records immutable content pulled from a registry. Tags are easy to read, but a digest is the reliable identity of the manifest. Many deployment systems allow image references like nginx@sha256:... so production uses exact content instead of whatever a tag points to later.
Tag an image for a private registry
docker tag nginx:1.27-alpine registry.example.com/platform/nginx-proxy:1.27.0-alpine
docker image ls registry.example.com/platform/nginx-proxy
Output:
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.example.com/platform/nginx-proxy 1.27.0-alpine 1a2b3c4d5e6f 2 weeks ago 48MB
The new name points to the same local image ID. Tagging does not rebuild the image and does not upload anything by itself. It only prepares a name that tells Docker which remote registry and repository should receive the image when you push.
Log in and push
docker login registry.example.com
docker push registry.example.com/platform/nginx-proxy:1.27.0-alpine
Output:
Username: platform-user
Password:
Login Succeeded
The push refers to repository [registry.example.com/platform/nginx-proxy]
1.27.0-alpine: digest: sha256:exampledigestforlessononly size: 856
docker login authenticates the client for the registry. During docker push, Docker checks which layer blobs the registry already has and uploads only missing ones. Then it uploads the manifest and assigns the tag to it. In real automation, prefer access tokens or CI-provided registry credentials over typing a personal password.
How it works step by step
- The Docker client parses the image name. If no hostname is present, it assumes Docker Hub. If no tag is present, it assumes
latest, which is convenient but often too vague for repeatable deployments. - The Docker daemon contacts the registry API and asks for the image manifest matching the requested tag or digest. For multi-platform images, the first response may be a manifest list or OCI index containing entries for Linux amd64, Linux arm64, and other platforms.
- The daemon chooses the platform that matches your Docker Engine. On Docker Desktop, Linux containers run inside a lightweight Linux VM, so the selected image is normally a Linux image even on macOS or Windows.
- Docker compares the manifest’s layer digests with layers already stored locally. Existing layers are reused. Missing layers are downloaded, verified by digest, decompressed, and stored in Docker’s content store.
- The image configuration is saved locally. It contains metadata such as environment variables, default command, exposed ports, working directory, labels, and history. Remember that
EXPOSEis only metadata; it does not publish a port to the host. Publishing requiresdocker run -por Composeports:. - When you push, the flow is mostly reversed. Docker verifies credentials, checks which blobs the registry already knows, uploads missing layers, uploads the manifest, and finally moves the tag to that manifest.
Common Mistakes
Depending on latest in production
docker run -d --name web nginx:latest
This is valid Docker syntax, but it is weak operational practice. latest is just a tag name, not a guarantee that the image is newest, stable, or compatible. A later pull can produce different content than an earlier pull. Use a specific version tag, and for the strictest reproducibility, deploy by digest.
docker run -d --name web nginx:1.27-alpine
Forgetting that tag does not push
docker tag myapp:1.0.0 registry.example.com/team/myapp:1.0.0
After this command, the image still exists only in the local Docker image store. Teammates, servers, and CI jobs cannot pull it until you run docker push registry.example.com/team/myapp:1.0.0 with permission to write that repository.
Baking secrets into an image
FROM node:20-alpine
ENV API_KEY=changeme
COPY . /app
Do not store real secrets in Dockerfiles or image layers. Even if a later layer deletes a file or changes an environment variable, older layers can still reveal what was added. Pass secrets at runtime through your orchestrator, secret store, mounted files, or environment variables managed outside the image.
Pulling from an untrusted namespace
docker pull randomuser/postgres:15
Names on public registries are not automatically trustworthy. Prefer official images, your organization’s images, or images from publishers you can verify. Review the Dockerfile or source repository when possible, pin versions, scan images, and restrict who can push to production repositories.
Best Practices
- Use explicit tags such as
1.0.0,1.0.0-alpine, or a build number instead of relying onlatest. - Record or deploy repository digests for production releases when you need exact reproducibility.
- Use a clear naming scheme:
registry.example.com/team/service:versionis easier to automate than ad hoc names. - Keep images small and focused. Smaller images push and pull faster and reduce the amount of code you must trust.
- Authenticate with tokens in CI, not personal passwords. Rotate credentials and grant the narrowest useful permissions.
- Separate development tags from release tags. For example,
main-20260803-1530can be temporary, while1.4.2is a release. - Make registry permissions part of your deployment design. Developers may need pull access, but only CI should push release tags.
- Scan images before promotion, and rebuild regularly so pinned base image tags still receive operating-system package updates when the publisher releases them.
- Do not confuse a registry repository with a Git repository. A registry stores image layers and manifests, not source code history.
Practice Exercises
- Pull
redis:7.2-alpine, inspect its repository digests, and identify the immutable digest Docker recorded locally. Hint: usedocker image inspect --format. - Build or reuse a local image named
myapp:1.0.0, then tag it for a registry path under your own Docker Hub username. Expected end state:docker image lsshows both names pointing to the same image ID. - Design a tag policy for a small team with development, staging, and production releases. Include which tags CI may overwrite and which tags should never move after release.
Summary
- Docker Hub is Docker’s default registry, but the registry model is the same for private and cloud registries.
- A registry stores image manifests and layer blobs; it does not run containers.
- Image names include an optional registry hostname, a namespace, a repository, and a tag or digest.
- Tags are convenient movable labels; digests identify exact image content.
docker pulldownloads manifests and missing layers, whiledocker pushuploads missing layers and publishes a manifest under a tag.- Use specific tags, trusted namespaces, least-privilege credentials, and digests for production-grade reproducibility.
