0
0
Dockerdevops~7 mins

Targeting specific stages in Docker - Commands & Configuration

Choose your learning style9 modes available
Introduction
When building Docker images, you can create multiple steps called stages. Targeting specific stages lets you build only part of the image, saving time and space.
When you want to build only the final app without the build tools to keep the image small
When you want to test or debug an intermediate stage separately
When you want to reuse a build stage for different final images
When you want to speed up builds by skipping unnecessary stages
When you want to create multiple images from one Dockerfile with different contents
Config File - Dockerfile
Dockerfile
FROM node:18 AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:1.23 AS production
COPY --from=builder /app/build /usr/share/nginx/html

FROM node:18 AS test
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
CMD ["npm", "test"]

This Dockerfile has three stages:

  • builder: installs dependencies and builds the app
  • production: copies built files from builder to nginx image
  • test: installs dependencies and runs tests

You can choose which stage to build or run.

Commands
Builds only the 'builder' stage to get the build environment and compiled app without creating the final image.
Terminal
docker build --target builder -t my-app-builder .
Expected OutputExpected
Sending build context to Docker daemon 12.34MB Step 1/7 : FROM node:18 AS builder ---> 123abc456def Step 2/7 : WORKDIR /app ---> Using cache ---> 789def012abc Step 3/7 : COPY package.json package-lock.json ./ ---> Using cache ---> 345abc678def Step 4/7 : RUN npm install ---> Running in 456def789abc added 100 packages in 5s Removing intermediate container 456def789abc ---> 901abc234def Step 5/7 : COPY . . ---> Using cache ---> 567def890abc Step 6/7 : RUN npm run build ---> Running in 678abc901def Build completed successfully Removing intermediate container 678abc901def ---> 234def567abc Successfully built 234def567abc Successfully tagged my-app-builder:latest
--target - Specifies which build stage to build
-t - Tags the image with a name
Builds the final production image by copying built files from the builder stage into the nginx base image.
Terminal
docker build --target production -t my-app-prod .
Expected OutputExpected
Sending build context to Docker daemon 12.34MB Step 1/9 : FROM node:18 AS builder ---> 123abc456def Step 2/9 : WORKDIR /app ---> Using cache ---> 789def012abc Step 3/9 : COPY package.json package-lock.json ./ ---> Using cache ---> 345abc678def Step 4/9 : RUN npm install ---> Using cache ---> 901abc234def Step 5/9 : COPY . . ---> Using cache ---> 567def890abc Step 6/9 : RUN npm run build ---> Using cache ---> 234def567abc Step 7/9 : FROM nginx:1.23 AS production ---> 456abc789def Step 8/9 : COPY --from=builder /app/build /usr/share/nginx/html ---> Using cache ---> 678def901abc Step 9/9 : ---> Using cache Successfully built 678def901abc Successfully tagged my-app-prod:latest
--target - Builds the specified stage
-t - Tags the image
Runs the production image to serve the built app using nginx.
Terminal
docker run --rm my-app-prod
Expected OutputExpected
No output (command runs silently)
--rm - Removes the container after it stops
Builds the test stage to run tests inside the container.
Terminal
docker build --target test -t my-app-test .
Expected OutputExpected
Sending build context to Docker daemon 12.34MB Step 1/7 : FROM node:18 AS test ---> 123abc456def Step 2/7 : WORKDIR /app ---> Using cache ---> 789def012abc Step 3/7 : COPY package.json package-lock.json ./ ---> Using cache ---> 345abc678def Step 4/7 : RUN npm install ---> Running in 456def789abc added 100 packages in 5s Removing intermediate container 456def789abc ---> 901abc234def Step 5/7 : COPY . . ---> Using cache ---> 567def890abc Step 6/7 : CMD ["npm", "test"] ---> Using cache Successfully built 567def890abc Successfully tagged my-app-test:latest
--target - Builds only the test stage
-t - Tags the image
Runs the test stage container to execute tests defined in the app.
Terminal
docker run --rm my-app-test
Expected OutputExpected
> my-app@1.0.0 test > jest PASS src/app.test.js ✓ renders without crashing (5 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 2.345 s
--rm - Removes container after test run
Key Concept

If you remember nothing else from this pattern, remember: the --target flag lets you build or run only the stage you want from a multi-stage Dockerfile.

Common Mistakes
Not specifying --target when building multi-stage Dockerfiles
Docker builds the last stage by default, which may be larger or not what you want
Use --target with the exact stage name to build only that stage
Using stage names that are not defined in the Dockerfile
Docker will fail with an error saying the target stage does not exist
Check the Dockerfile for exact stage names and use those with --target
Trying to run intermediate build stages without CMD or ENTRYPOINT
Containers will exit immediately because no command is specified
Add CMD or ENTRYPOINT in the stage if you want to run it as a container
Summary
Use multi-stage Dockerfiles to separate build, test, and production steps.
Use docker build --target stage_name to build only a specific stage.
Run images built from specific stages to test or deploy parts of your app.