docker tag
docker tag adds a new name to an image that already exists in your local Docker image store. It matters because registries, teams, CI systems, and deployments all identify images by repository names and tags, not by vague descriptions like the image I just built. Retagging is how you turn a local image such as web-demo:1.0 into a registry-ready reference such as registry.example.com/team/web-demo:1.0.
Overview: How docker tag Works
A Docker image is read-only content: a configuration object plus a stack of filesystem layers. The local Docker image store can keep several references that all point to the same image ID. A reference includes a repository name and usually a tag, such as web-demo:1.0. When you run docker tag, Docker does not rebuild the image, copy layers, or contact a registry. It simply records another local reference to the same image content.
This is easier to understand if you separate image content from image names. The content is identified internally by digests and image IDs. The name is a human and registry-facing label. If web-demo:1.0 and registry.example.com/team/web-demo:1.0 show the same image ID in docker image ls, they are two names for one local image, not two independent images.
Image references have a structured form: [registry-host[:port]/][namespace/]repository[:tag]. The short reference nginx:1.27-alpine uses Docker Hub by default. A private registry reference includes a host name, such as registry.example.com/team/api:2.3.0. The tag is the part after the final colon. If you omit the tag, Docker assumes latest, which is only an ordinary tag name. It does not mean newest or safest.
docker tag is commonly used after a build. You might build a local image as payments-api:2026.08.03, test it, then add registry.example.com/platform/payments-api:2026.08.03 so it can be pushed. The push step is separate. docker push uploads missing layer blobs, uploads a manifest, and sets the remote tag in the registry. Until you push, the new tag exists only on your machine.
Tags are mutable unless your registry or release process prevents movement. Locally, retagging an existing target name points that target at different image content. Remotely, pushing a tag that already exists can move the registry tag. This is useful for moving channel names like staging or stable, but release tags such as 1.4.2 should usually be treated as immutable.
Syntax
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
| Part | Meaning |
|---|---|
SOURCE_IMAGE[:TAG] |
The existing local image reference. You may also use an image ID instead of a name. |
TARGET_IMAGE[:TAG] |
The new local image reference to create. Include the registry host and namespace when preparing to push. |
:TAG |
The image tag. If omitted, Docker uses :latest. |
registry-host |
The registry location, such as registry.example.com, ghcr.io, or localhost:5000. |
namespace |
An account, organization, or project path used by the registry. |
There are no important behavioral flags for docker tag. The command is intentionally small: source reference in, target reference out. The related command docker image tag is an alias with the same behavior.
Examples
Example 1: Add a Version Tag to a Local Image
docker pull alpine:3.20
docker tag alpine:3.20 tiny-base:3.20
docker image ls tiny-base
Output:
3.20: Pulling from library/alpine
Digest: sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1
Status: Downloaded newer image for alpine:3.20
docker.io/library/alpine:3.20
REPOSITORY TAG IMAGE ID CREATED SIZE
tiny-base 3.20 324bc02ae123 4 weeks ago 7.8MB
Docker pulled alpine:3.20, then added tiny-base:3.20 as another local reference. The underlying layers were not copied. If you also list alpine:3.20, it will have the same image ID as tiny-base:3.20.
Example 2: Build Once, Then Tag for a Registry
FROM nginx:1.27-alpine
COPY index.html /usr/share/nginx/html/index.html
docker build -t web-demo:1.0 .
docker tag web-demo:1.0 registry.example.com/team/web-demo:1.0
docker image ls registry.example.com/team/web-demo
Output:
[+] Building 1.6s (7/7) FINISHED
=> exporting to image
=> naming to docker.io/library/web-demo:1.0
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.example.com/team/web-demo 1.0 9b1f2c3d4e5f 12 seconds ago 48.3MB
The Dockerfile uses a pinned base tag, nginx:1.27-alpine, instead of nginx or latest. The build creates the local image web-demo:1.0. The tag command then adds the registry-qualified name that docker push would use. Nothing has been uploaded yet.
Example 3: Create Release and Channel Tags
docker tag web-demo:1.0 registry.example.com/team/web-demo:2026.08.03
docker tag web-demo:1.0 registry.example.com/team/web-demo:stable
docker image ls registry.example.com/team/web-demo
Output:
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.example.com/team/web-demo 1.0 9b1f2c3d4e5f 2 minutes ago 48.3MB
registry.example.com/team/web-demo 2026.08.03 9b1f2c3d4e5f 2 minutes ago 48.3MB
registry.example.com/team/web-demo stable 9b1f2c3d4e5f 2 minutes ago 48.3MB
This pattern gives the same tested image multiple useful names. 2026.08.03 is an immutable release-style tag. stable is a moving channel tag that can later point to a newer tested image. Docker does not enforce those meanings; your team and registry policies do.
Example 4: Tag and Push to a Local Registry
docker run -d -p 5000:5000 --name local-registry registry:2
docker tag web-demo:1.0 localhost:5000/web-demo:1.0
docker push localhost:5000/web-demo:1.0
Output:
The push refers to repository [localhost:5000/web-demo]
5f70bf18a086: Pushed
d4fc045c9e3a: Pushed
1.0: digest: sha256:30f2f3d7a51b4a1f58fb38dfc6b26b04caa6c7d50a9fb8a4d7a4d01fd7f4b8b2 size: 856
Here the first command starts a registry container on your machine. The tag adds a name whose registry host is localhost:5000. The push uploads the image content and creates the remote 1.0 tag in that registry. docker tag prepared the name; docker push performed the distribution.
How It Works Step by Step
- The Docker CLI sends the source and target image references to the Docker daemon.
- The daemon resolves the source reference in the local image store. If the source tag is omitted, it looks for
latest. - Docker verifies that the source image exists locally.
docker tagdoes not automatically pull missing source images. - The daemon parses the target reference into registry host, namespace, repository, and tag components.
- Docker records the target reference as another name for the same image ID and layer chain.
- If the target reference already existed locally, it now points at the new source image.
- No image layers are copied, compressed, rebuilt, or uploaded during the tag operation.
- Later,
docker push TARGET_IMAGE:TAGcontacts the target registry, uploads missing blobs, uploads a manifest, and sets the remote tag.
When a container is eventually started from the tagged image, Docker still uses the same mechanics as any other image: it mounts the read-only image layers, adds a thin writable container layer, and starts the configured process. The tag chosen at run time only selects which image content to use.
Common Mistakes
Expecting docker tag to Push
docker tag web-demo:1.0 registry.example.com/team/web-demo:1.0
This creates a local name only. A teammate or server cannot pull that tag from the registry until you push it:
docker push registry.example.com/team/web-demo:1.0
Forgetting the Registry Host
docker tag web-demo:1.0 team/web-demo:1.0
This does not name registry.example.com. Without an explicit host, Docker treats it as a Docker Hub-style name. Use the complete registry-qualified reference when preparing for a private registry:
docker tag web-demo:1.0 registry.example.com/team/web-demo:1.0
Accidentally Creating latest
docker tag web-demo:1.0 registry.example.com/team/web-demo
Because no target tag was written, Docker creates registry.example.com/team/web-demo:latest. That may be acceptable for a development convenience tag, but it is a poor production release identifier. Write the target tag explicitly:
docker tag web-demo:1.0 registry.example.com/team/web-demo:1.0
Treating a Retag as a Backup
docker tag web-demo:1.0 web-demo:backup
This is only another local reference to the same image content. It is not an independent archive. If the host is lost, the tag is lost too. Durable storage comes from pushing to a registry and keeping the source, Dockerfile, build inputs, and release metadata.
Best Practices
- Use explicit target tags. Avoid relying on implicit
latest. - Include the registry host when preparing an image for a private registry, for example
registry.example.com/team/app:1.0.0. - Treat release tags as immutable. Publish
1.0.1instead of moving1.0.0to changed content. - Use channel tags such as
stable,staging, ordevonly when a moving pointer is intentional. - Build with a specific tag, retag the exact tested image, then push the registry-qualified tag.
- Record the digest printed by
docker pushfor audits and reproducible deployments. - Use pinned base image tags in Dockerfiles, such as
nginx:1.27-alpine, and rebuild regularly for updates. - Do not bake secrets into images before tagging or pushing them. Image layers and metadata can persist even after later changes.
- Clean up unwanted local references with
docker image rm name:tag, understanding that image content remains if another tag or container still references it.
Practice Exercises
- Pull
alpine:3.20, tag it aslab-alpine:3.20, and list both references. Expected end state: both names point to the same image ID. - Build a small static Nginx image named
site-demo:0.1.0, then add a registry-qualified tag forlocalhost:5000/site-demo:0.1.0. Hint: tagging does not require the registry to be running. - Design a tagging scheme for a service that has development, staging, and production environments. Include one immutable release tag and one moving channel tag, and decide which one your deployment scripts should use.
Summary
docker tagcreates a new local image reference for existing image content.- It does not rebuild layers, copy image data, pull missing images, or push to a registry.
- Registry-ready names include a registry host, namespace, repository, and explicit tag.
- Omitting a tag creates or uses
latest, which is just an ordinary mutable tag name. - Use immutable release tags for reproducibility and moving channel tags only when intentional.
- Distribution happens with
docker push, which uploads missing blobs and sets the remote registry tag.
