Bird
Raised Fist0
Dockerdevops~5 mins

Builder pattern before multi-stage in Docker - Commands & Configuration

Choose your learning style10 modes available
Introduction
Sometimes, building a Docker image requires compiling code or preparing files before creating the final image. Before Docker had multi-stage builds, developers used the builder pattern to separate the build steps into different images to keep the final image small and clean.
When you need to compile source code before running your app in a Docker container.
When you want to keep your final Docker image small by excluding build tools.
When your Docker version does not support multi-stage builds.
When you want to reuse a build image for multiple final images.
When you want to separate build and runtime environments clearly.
Config File - Dockerfile
Dockerfile
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

FROM alpine:3.18
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]

The first part uses the official Go image to build the app. It copies the source code and runs the build command.

The second part uses a small Alpine Linux image and copies only the built binary from the builder image. This keeps the final image small and clean.

Commands
This command builds the Docker image using the Dockerfile. It creates the builder image that compiles the app and then the final image with the compiled binary.
Terminal
docker build -t myapp-builder -f Dockerfile .
Expected OutputExpected
[+] Building 10.5s (8/8) FINISHED => [internal] load build definition from Dockerfile 0.1s => => transferring dockerfile: 123B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/golang:1.20 1.2s => [builder 1/4] FROM docker.io/library/golang:1.20 1.2s => [builder 2/4] WORKDIR /app 0.1s => [builder 3/4] COPY . . 0.5s => [builder 4/4] RUN go build -o myapp 8.3s => [final 1/3] FROM docker.io/library/alpine:3.18 0.5s => [final 2/3] WORKDIR /app 0.1s => [final 3/3] COPY --from=builder /app/myapp . 0.1s => exporting to image 0.3s => => exporting layers 0.3s => => writing image sha256:abcdef1234567890 0.0s => => naming to docker.io/library/myapp-builder
→
-t - Assigns a name and optionally a tag to the image.
→
-f - Specifies the Dockerfile to use.
Runs the final image to verify the built application works as expected.
Terminal
docker run --rm myapp-builder
Expected OutputExpected
Hello from myapp!
→
--rm - Automatically removes the container after it exits.
Lists all Docker images to confirm the builder and final images exist.
Terminal
docker images
Expected OutputExpected
REPOSITORY TAG IMAGE ID CREATED SIZE myapp-builder latest abcdef123456 10 seconds ago 25MB
Key Concept

If you remember nothing else from this pattern, remember: use a separate build image to compile your app and copy only the final artifact into a small runtime image.

Common Mistakes
Copying source code directly into the final image instead of the built binary.
This makes the final image large and includes unnecessary build tools and files.
Use the builder pattern to build in one image and copy only the compiled binary to the final image.
Not specifying the correct Dockerfile with -f when building.
Docker might use a different Dockerfile or fail to find the build instructions.
Always use -f Dockerfile to specify the correct file if not named Dockerfile or in a different location.
Summary
Use a builder image to compile or prepare your app with all necessary tools.
Copy only the final built artifact into a small runtime image to keep it lightweight.
Build and run the image to verify your app works as expected.

Practice

(1/5)
1. What is the main purpose of the builder pattern in Docker before multi-stage builds were introduced?
easy
A. To run multiple containers simultaneously
B. To separate the build environment from the final runtime environment
C. To automatically update Docker images
D. To manage Docker volumes efficiently

Solution

  1. Step 1: Understand the builder pattern concept

    The builder pattern splits the process into two parts: building the app and running it.
  2. Step 2: Identify the benefit of separation

    This separation keeps the final image small by excluding build tools and files.
  3. Final Answer:

    To separate the build environment from the final runtime environment -> Option B
  4. Quick Check:

    Builder pattern = separate build and run [OK]
Hint: Builder pattern means build and run are separate stages [OK]
Common Mistakes:
  • Confusing builder pattern with running multiple containers
  • Thinking it manages volumes or updates automatically
  • Assuming it is about Docker networking
2. Which Dockerfile snippet correctly implements the builder pattern before multi-stage builds?
easy
A. FROM node:14 WORKDIR /app COPY . . RUN npm install && npm run build CMD ["npm", "start"]
B. FROM node:14 AS builder WORKDIR /app COPY . . RUN npm install && npm run build FROM nginx:alpine COPY --from=builder /app/build /usr/share/nginx/html
C. FROM node:14 RUN npm install COPY . . CMD ["npm", "start"]
D. FROM nginx:alpine COPY . /usr/share/nginx/html RUN npm install

Solution

  1. Step 1: Identify builder pattern before multi-stage

    Before multi-stage, builder pattern used separate Dockerfiles or manual copying, not the --from syntax.
  2. Step 2: Check each option

    FROM node:14 AS builder WORKDIR /app COPY . . RUN npm install && npm run build FROM nginx:alpine COPY --from=builder /app/build /usr/share/nginx/html uses multi-stage syntax (--from=builder), which was not available before multi-stage builds.
  3. Final Answer:

    FROM node:14 WORKDIR /app COPY . . RUN npm install && npm run build CMD ["npm", "start"] -> Option A
  4. Quick Check:

    Before multi-stage, no --from usage [OK]
Hint: Before multi-stage, no --from in COPY command [OK]
Common Mistakes:
  • Choosing multi-stage syntax before it existed
  • Confusing build and runtime commands
  • Ignoring the CMD instruction
3. Given this Dockerfile before multi-stage builds:
FROM node:14
WORKDIR /app
COPY . .
RUN npm install && npm run build
CMD ["node", "server.js"]

What is the likely size impact on the final image?
medium
A. The image will be large because build tools and source files remain
B. The image will be small because only build output is copied
C. The image size is minimal due to automatic cleanup
D. The image size depends only on the base image

Solution

  1. Step 1: Analyze the Dockerfile steps

    The Dockerfile copies all source files and runs build inside the same image.
  2. Step 2: Understand image size impact

    Since build tools and source files remain, the image size is larger than needed.
  3. Final Answer:

    The image will be large because build tools and source files remain -> Option A
  4. Quick Check:

    Single-stage build keeps all files, so image is large [OK]
Hint: Single-stage build keeps all files, making image large [OK]
Common Mistakes:
  • Assuming build output only is copied
  • Thinking Docker cleans up build files automatically
  • Ignoring the COPY . . step
4. You have two Dockerfiles: one for building and one for running. You want to copy build artifacts from the builder image to the runtime build context manually. Which command correctly copies files from a stopped builder container named 'builder' to the runtime build context?
medium
A. docker cp ./build builder:/app/build
B. docker copy builder:/app/build ./build
C. docker cp builder:/app/build ./build
D. docker copy ./build builder:/app/build

Solution

  1. Step 1: Understand docker cp syntax

    The correct syntax is 'docker cp <container>:<source_path> <destination_path>'.
  2. Step 2: Match command to copy from container to local

    docker cp builder:/app/build ./build correctly copies from container 'builder' path to local './build'.
  3. Final Answer:

    docker cp builder:/app/build ./build -> Option C
  4. Quick Check:

    docker cp container:path local_path [OK]
Hint: Use 'docker cp container:path local_path' to copy files out [OK]
Common Mistakes:
  • Using 'docker copy' instead of 'docker cp'
  • Reversing source and destination paths
  • Trying to copy from local to container incorrectly
5. You want to manually implement the builder pattern before multi-stage builds by using two Dockerfiles: Dockerfile.build and Dockerfile.run. Which sequence of commands correctly builds and prepares the final image with only the build output copied?
hard
A. docker build -f Dockerfile.build -t app-builder . && docker run --name builder app-builder && docker cp builder:/app/dist ./dist && docker rm builder && docker build -f Dockerfile.run -t app-runtime .
B. docker build -f Dockerfile.run -t app-runtime . && docker build -f Dockerfile.build -t app-builder .
C. docker build -f Dockerfile.run -t app-runtime . && docker run --name builder app-builder && docker cp builder:/app/dist ./dist
D. docker build -f Dockerfile.build -t app-builder . && docker create --name builder app-builder && docker cp builder:/app/dist ./dist && docker rm builder && docker build -f Dockerfile.run -t app-runtime .

Solution

  1. Step 1: Build the builder image and create a container

    Use 'docker build' with Dockerfile.build, then 'docker create' to make a stopped container for copying files.
  2. Step 2: Copy build output and build runtime image

    Copy files from the builder container, remove it, then build the runtime image with Dockerfile.run.
  3. Final Answer:

    docker build -f Dockerfile.build -t app-builder . && docker create --name builder app-builder && docker cp builder:/app/dist ./dist && docker rm builder && docker build -f Dockerfile.run -t app-runtime . -> Option D
  4. Quick Check:

    Build, create, copy, remove, then build runtime [OK]
Hint: Create container to copy files, then build runtime image [OK]
Common Mistakes:
  • Using 'docker run' instead of 'docker create' for copying
  • Building runtime image before copying build output
  • Not removing temporary builder container
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard