✦ For everyone, free.

Practical knowledge for real and everyday life

Home

19.1.1.5 Build Target Option

A focused guide to Build Target Option, connecting core concepts with practical Docker and container operations.

The build target option, --target, selects which specific named stage in a multi-stage Dockerfile a build should actually produce as its final result, and understanding its validation behavior, its use for debugging intermediate stages directly, and its limitation to one target per invocation clarifies how to use it effectively beyond the basic build-versus-production stage selection already covered in multi-stage best practice content.

Basic stage selection

FROM node:20 AS build
RUN npm run build

FROM node:20-alpine AS production
COPY --from=build /app/dist ./dist
docker build --target production -t my-api:prod .
docker build --target build -t my-api:build-debug .

Without --target, a build produces the file's final stage by default; specifying it explicitly produces whichever named stage was requested instead, stopping the build process at that point rather than continuing through any subsequent stages defined after it in the file.

Validation and error behavior for an invalid target name

Specifying a target name that does not actually exist in the Dockerfile produces a clear, immediate error rather than silently falling back to some default behavior:

docker build --target productoin -t my-api .
failed to solve: target stage "productoin" could not be found

This typo-driven error is fast and unambiguous to diagnose, simply correcting the misspelled stage name, which is a relatively forgiving failure mode compared to some other categories of build misconfiguration that might instead produce a more subtle, harder-to-diagnose incorrect result.

Building an intermediate stage directly for debugging

Targeting an earlier, intermediate stage directly, rather than only ever building the final production stage, is a useful and common debugging technique for investigating exactly what an earlier stage produced before any subsequent stage's COPY --from= instruction selectively pulled specific content from it:

docker build --target build -t my-api:debug-build .
docker run -it --rm my-api:debug-build sh
ls -la /app/dist

Running an interactive shell directly within this intermediate stage's own image confirms exactly what files and structure actually existed at that point in the build, which is considerably faster than guessing based on the Dockerfile's apparent logic alone when a later stage's COPY --from= instruction seems to be missing an expected file.

Combining target selection with output extraction

Pairing --target with the --output flag covered in dedicated build CLI flag content extracts a specific intermediate stage's filesystem content directly to the host, without needing to load it as a runnable image and then manually copy files out of a container afterward:

docker buildx build --target build --output type=local,dest=./extracted-build .

This is particularly useful for a build whose intermediate stage produces artifacts genuinely meant for direct host extraction, compiled binaries, generated documentation, rather than something intended to become a runnable container image at all.

One target per build invocation

A single docker build invocation produces exactly one target's result; building multiple distinct targets from the same Dockerfile requires separate, individual build invocations, one per target, each its own complete command:

docker build --target development -t my-api:dev .
docker build --target production -t my-api:prod .
docker build --target debug -t my-api:debug .

For projects needing to routinely build several targets together as part of a single workflow, docker buildx bake, a separate, related tool, supports defining and building multiple targets in one invocation through a structured configuration file, which is the appropriate tool to reach for once building several targets individually through repeated, separate docker build commands becomes a recurring, routine need rather than an occasional, manual task.

target "dev" {
  target = "development"
  tags = ["my-api:dev"]
}
target "prod" {
  target = "production"
  tags = ["my-api:prod"]
}
docker buildx bake

Common mistakes

  • Assuming a single build invocation can produce more than one target's result, rather than recognizing that each target requires its own separate, individual build command.
  • Not using --target to build and inspect an intermediate stage directly when debugging an unexpected or missing result in a later stage's selective copy from it.
  • Misreading a target-not-found error as a more general, unrelated build failure rather than recognizing it as a simple, easily corrected stage name typo.
  • Not considering docker buildx bake once routinely building several distinct targets from the same Dockerfile becomes a recurring, repeated manual task.
  • Forgetting that --target stops the build at the specified stage entirely, never executing any subsequent stage defined after it in the Dockerfile.

The build target option's validation behavior makes a misspelled stage name fast and clear to diagnose, its ability to build and inspect any intermediate stage directly is a genuinely useful debugging technique, and its one-target-per-invocation limitation is worth knowing about explicitly so that docker buildx bake can be reached for once building multiple targets together becomes a routine, recurring workflow need.