docker build -t reference
Last reviewed on 2026-08-27
Naming and tagging an image at build time: syntax rules, multiple tags, registry prefixes, and what :latest really means.
Syntax
-t is the short form of --tag. It gives the image a name so you can refer to it later. Everything except NAME is optional.
The -t flag on docker build answers the question "what do I call this thing?". A build without -t still succeeds and still produces a real image, but that image has no name: it shows up in docker images as <none>:<none> and the only way to run it is by its ID. That is why almost every build command you will see in the wild carries a -t.
# Named and tagged
docker build -t myapp:1.4.2 .
# Named, tag omitted — Docker fills in :latest
docker build -t myapp .
# No -t at all — a dangling image you must address by ID
docker build .
Anatomy of an image reference
A full image reference has up to four parts. Docker fills in defaults for the ones you leave out:
| Part | Example | Default if omitted |
|---|---|---|
| Registry host (and port) | ghcr.io, registry.example.com:5000 | Docker Hub (docker.io) |
| Namespace / user | acme | library on Docker Hub — which is why ubuntu resolves to docker.io/library/ubuntu |
| Repository name | myapp | Required. This is the minimum -t accepts. |
| Tag | 1.4.2 | latest |
Docker decides whether the first segment is a registry host or a namespace by looking for a dot, a colon, or the literal string localhost. acme/myapp is the acme namespace on Docker Hub; acme.io/myapp is the myapp repository on the registry acme.io. This one rule causes a surprising amount of confusion when a company's namespace happens to look like a hostname.
Rules the name and tag must follow
- The repository name must be lowercase.
docker build -t MyApp .fails withinvalid reference format: repository name must be lowercase. Onlya–z,0–9, and the separators.,_,-are allowed, and it may not start or end with a separator. - The tag may contain uppercase. Tags accept
A–Z,a–z,0–9,_,.and-, must not begin with.or-, and are capped at 128 characters.myapp:Release-2024.1is legal. - A tag may not contain a slash or a colon. This is what breaks builds that try to tag with a Git branch name:
feature/loginis not a valid tag. Sanitise branch names in CI (${BRANCH//\//-}) before passing them to-t. - Everything after the last colon is the tag, unless that colon is part of a registry port.
registry.example.com:5000/myapphas no tag;registry.example.com:5000/myapp:1.0does.
Applying several tags in one build
Repeat -t as many times as you need. The image is built once and every tag points at the same image ID, so this costs nothing extra:
docker build \
-t myapp:1.4.2 \
-t myapp:1.4 \
-t myapp:latest \
-t ghcr.io/acme/myapp:1.4.2 \
.
This is the standard release pattern: an immutable exact version, a moving minor-version alias, a moving latest, and a copy of the exact version under the registry you will push to. Note that -t only names the image locally — pushing is a separate step, and docker push pushes one reference at a time:
docker push ghcr.io/acme/myapp:1.4.2
docker push ghcr.io/acme/myapp:latest
What :latest actually means
latest is not a special "newest" pointer maintained by Docker. It is simply the tag Docker substitutes when you do not write one, in both docker build -t myapp . and docker run myapp. It points at whatever image was most recently tagged latest, which can easily be older than other tags in the same repository — for example if you build myapp:2.0 without also tagging it latest.
Two practical consequences:
- Do not deploy
:latest. Deploy an immutable version tag, or better, a digest (myapp@sha256:…). A mutable tag makes rollbacks and incident forensics much harder, and it makesFROMlines non-reproducible. - Tag it anyway for humans.
:latestis a genuinely useful convenience for local development and fordocker rundemos. Publish it, just do not build your rollout on it.
Retagging an image you already built
If you forgot a tag, you do not need to rebuild. docker tag adds another name to an existing image ID:
# Add a registry-qualified name to an image already built as myapp:1.4.2
docker tag myapp:1.4.2 ghcr.io/acme/myapp:1.4.2
# Rename a dangling image you built without -t
docker build . -q # prints sha256:abc123…
docker tag sha256:abc123 myapp:1.4.2
Removing a tag with docker rmi myapp:1.4 deletes only that name. The image itself survives as long as at least one tag or container still references it.
Tagging in CI
The two values worth tagging with are the commit SHA (unique, immutable, always available) and the release version (human-readable, only meaningful on tagged commits):
SHA=$(git rev-parse --short HEAD)
docker build \
-t "ghcr.io/acme/myapp:sha-${SHA}" \
-t "ghcr.io/acme/myapp:latest" \
--build-arg "VERSION=${SHA}" \
.
Passing the same value in as a --build-arg lets the application report its own version, but be aware it changes the cache key of every instruction after the ARG is referenced — so reference it as late in the Dockerfile as possible.
Tagging multi-platform builds
With docker buildx, a single -t can name a manifest list covering several architectures. The tag then resolves per-platform at pull time:
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/acme/myapp:1.4.2 \
--push .
Note the --push: a multi-platform result cannot be loaded into the local image store, so it goes straight to the registry. See the multi-architecture builds tutorial for the full workflow.
Common errors
| Message | Cause |
|---|---|
invalid reference format: repository name must be lowercase | An uppercase letter in the repository name — often a project name or a $USER variable interpolated straight into -t. |
invalid reference format | A slash or colon inside the tag (a raw Git branch name), a trailing separator, or an empty tag after the colon. |
"docker build" requires exactly 1 argument | The context path is missing. -t consumes the value after it, so docker build -t myapp leaves nothing for the path — you need the trailing .. |
denied: requested access to the resource is denied on push | The tag's registry or namespace does not match the account you are logged in to. Retag with docker tag rather than rebuilding. |
Related
docker buildcommand reference — every other flag, in one place.docker build -freference — pointing the build at a Dockerfile somewhere else.- docker push and pull reference — getting a tagged image into a registry.
docker imagereference — listing, tagging and removing images after the build.- FROM reference — why the tags you consume deserve as much care as the ones you publish.