Skip to content

Build, Tag & the Build Context

docker build reads a Dockerfile and produces an image. The basic syntax is:

Terminal window
docker build [OPTIONS] PATH

The PATH argument (usually .) is called the build context — it is the directory that Docker sends to the build daemon. Files in the build context are available to COPY instructions inside the Dockerfile. Files outside the build context are not accessible.

Terminal window
docker build .

This sends the current directory as the build context. Without -t, the resulting image has no name — only a hex digest. You will almost always add -t.

The -t flag assigns a human-readable name:tag to the image:

Terminal window
docker build -t myapp:1.0 .

The full form of a tag is:

[registry/][owner/]name:tag

Examples:

myapp:1.0
myapp:latest
ghcr.io/acme/myapp:1.0
docker.io/library/node:22-alpine

If you omit the tag part, Docker defaults to :latest.

Terminal window
docker images

Expected output:

REPOSITORY TAG IMAGE ID CREATED SIZE
myapp 1.0 a3f2b1c9d4e7 2 minutes ago 145MB
myapp latest a3f2b1c9d4e7 2 minutes ago 145MB
node 22-alpine 1b2c3d4e5f60 3 weeks ago 52MB

docker tag adds a new name or tag to an existing image without copying it. Both names point to the same image ID.

Terminal window
# Promote a build image to a release name
docker tag myapp:1.0 myapp:stable
docker tag myapp:1.0 ghcr.io/acme/myapp:1.0

latest is not a magic “newest” tag. It is just a default string that Docker uses when you omit the tag. It has no semantic version meaning. If you push myapp:1.0 and myapp:latest independently, they can point to completely different image layers.

In production pipelines, always use an explicit, meaningful tag (version number, git SHA, date) so you know exactly what is deployed.

Speeding up the context with .dockerignore

Section titled “Speeding up the context with .dockerignore”

By default, docker build . sends your entire current directory to the daemon — including node_modules/, .git/, test fixtures, and local secrets. A .dockerignore file (same syntax as .gitignore) excludes paths from the build context, which:

  • Speeds up the build (less data to transfer)
  • Prevents accidentally COPY-ing secrets into your image
.dockerignore
node_modules/
.git/
.env
*.log
dist/
coverage/
Terminal window
# Build with a version tag
docker build -t myapp:1.0 .
# Also tag as latest
docker tag myapp:1.0 myapp:latest
# Inspect the result
docker images myapp

Expected output:

REPOSITORY TAG IMAGE ID CREATED SIZE
myapp 1.0 a3f2b1c9d4e7 1 minute ago 145MB
myapp latest a3f2b1c9d4e7 1 minute ago 145MB
# syntax=docker/dockerfile:1
FROM alpine:3.20
LABEL maintainer="[email protected]"
WORKDIR /app
RUN echo "v1.0" > version.txt
CMD ["cat", "version.txt"]
# --- build, tag, and inspect ---
# docker build -t myapp:1.0 .
# docker tag myapp:1.0 myapp:latest
# docker images myapp
# docker run --rm myapp:1.0
What is the build context in `docker build .`?
What does `docker tag myapp:1.0 myapp:stable` do?
What is the main purpose of a .dockerignore file?
Which statement about the `latest` tag is true?