Tag, Push & Pull
The full image name
Section titled “The full image name”Every Docker image has a fully-qualified name made of four parts:
registry/namespace/repository:tag| Part | Example | Default |
|---|---|---|
| registry | docker.io | docker.io |
| namespace | acme | library (for official images) |
| repository | api-server | — |
| tag | 2.1.0 | latest |
So nginx is shorthand for docker.io/library/nginx:latest, and acme/api-server:2.1.0 means docker.io/acme/api-server:2.1.0.
For GHCR (GitHub Container Registry) the pattern is:
ghcr.io/<github-owner>/<repository>:<tag>docker tag — add a name to an image
Section titled “docker tag — add a name to an image”docker tag does not copy the image. It adds a new pointer to the same set of layers:
# Build the image locallydocker build -t api-server:2.1.0 .
# Add a registry-qualified name ready to pushdocker tag api-server:2.1.0 acme/api-server:2.1.0
# Also tag as latest (optional)docker tag api-server:2.1.0 acme/api-server:latestBoth acme/api-server:2.1.0 and acme/api-server:latest now refer to the exact same image ID — no extra storage is used.
docker push — upload to a registry
Section titled “docker push — upload to a registry”Push requires authentication (see the Docker Hub lesson). After docker login:
docker push acme/api-server:2.1.0docker push acme/api-server:latestEach layer is uploaded once and deduplicated on the registry. If another image already has the same layer, Docker skips it.
Expected output:
The push refers to repository [docker.io/acme/api-server]abc123def456: Pushed789ghijkl012: Layer already exists2.1.0: digest: sha256:deadbeef... size: 1234docker pull — download from a registry
Section titled “docker pull — download from a registry”# Pull a specific versiondocker pull acme/api-server:2.1.0
# Pull from GHCRdocker pull ghcr.io/acme/api-server:2.1.0If the image already exists locally, Docker checks whether the remote digest has changed and only downloads updated layers.
Semantic version tags and latest
Section titled “Semantic version tags and latest”A good tagging strategy uses multiple tags for the same image:
docker tag api-server:2.1.0 acme/api-server:2.1.0 # exact versiondocker tag api-server:2.1.0 acme/api-server:2.1 # minor streamdocker tag api-server:2.1.0 acme/api-server:2 # major streamdocker tag api-server:2.1.0 acme/api-server:latest # latest (optional)Consumers can pin to 2.1.0 for stability or follow 2 for non-breaking updates. latest is just a convenience alias — it has no automatic semantics.
Treat pushed tags as immutable
Section titled “Treat pushed tags as immutable”Once a tag has been pushed and other systems have started pulling it, never overwrite it. Re-pushing 2.1.0 with different content breaks reproducibility — other teams’ deployments may pull a different image than yours even though the tag looks the same.
Instead, always create a new tag (2.1.1, 2.2.0) for changed content.
Hands-on: pull and run a versioned public image
Section titled “Hands-on: pull and run a versioned public image”You cannot push to Docker Hub from Play with Docker (no credentials), but you can practice docker pull, docker tag, and docker run on a public image.
# Pull a specific nginx version
docker pull nginx:1.27-alpine
# Add a local alias tag
docker tag nginx:1.27-alpine my-nginx:stable
# Check both tags point to the same image ID
docker images nginx
docker images my-nginx
# Run it to verify it works
docker run --rm -d --name test-nginx -p 8080:80 my-nginx:stable
curl http://localhost:8080
docker stop test-nginx