SyntaxStudy
Sign Up
Docker Targeting Build Stages with --target
Docker Beginner 1 min read

Targeting Build Stages with --target

The --target flag for docker build stops the build at a named stage, producing an image from that stage only. This is used to extract the test stage as a separate image for running tests in CI, or to build the development stage which includes a shell and debugging tools that should not exist in the production image. Combining --target with Compose override files creates a clean local development workflow: the base Dockerfile defines dev, test, and production stages; the Compose override targets the dev stage which includes nodemon and a debugger. The production Dockerfile is the same file — no separate files to keep in sync. Caching is preserved across stage boundaries in BuildKit. If the deps stage has not changed (lock file is the same), its cached layer is reused even when the build stage changes. Named stages also make large Dockerfiles readable: stage names act as self-documenting section headers that communicate the purpose of each segment of the build.
Example
# Dockerfile with dev, test, and production targets

FROM node:20-alpine AS base
WORKDIR /app
COPY package.json package-lock.json ./

# dev stage (includes all deps + hot reload)
FROM base AS dev
RUN npm install
COPY . .
ENV NODE_ENV=development
CMD ["node","--watch","src/server.js"]

# test stage (run test suite at build time)
FROM dev AS test
RUN npm test

# production deps
FROM base AS prod-deps
RUN npm ci --omit=dev

# production stage
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=prod-deps /app/node_modules ./node_modules
COPY src/ ./src/
ENV NODE_ENV=production PORT=3000
EXPOSE 3000
CMD ["node","src/server.js"]

# Build dev image
# docker build --target dev -t myapp:dev .

# Run tests (build fails if tests fail)
# docker build --target test -t myapp:test .

# Build production image
# docker build --target production -t myapp:prod .