📖 Scenario: You are working on a Docker project where you want to create a small and efficient container image for a simple Go application. You want to learn how multi-stage builds help reduce the final image size by separating build and runtime environments.
🎯 Goal: Build a Dockerfile using multi-stage builds that compiles a Go program in one stage and copies only the compiled binary to a smaller base image in the final stage. This will show how multi-stage builds reduce image size.
📋 What You'll Learn
Create a Dockerfile with two stages: a build stage and a final stage
Use golang:1.20 as the build stage base image
Compile a Go program called hello.go in the build stage
Use alpine:latest as the final stage base image
Copy only the compiled binary from the build stage to the final stage
Set the container to run the compiled binary
💡 Why This Matters
🌍 Real World
Developers often need to create small, efficient Docker images to save bandwidth and speed up deployment.
💼 Career
Understanding multi-stage builds is important for DevOps roles to optimize container images and improve CI/CD pipelines.
Progress0 / 4 steps
1
Create the Go source file
Create a file named hello.go with a simple Go program that prints "Hello, Docker!" when run. The program should have a main package and a main function with fmt.Println("Hello, Docker!").
Docker
Hint
Use package main and import fmt. The main function should print the message.
2
Set up the build stage in Dockerfile
In a file named Dockerfile, create the first stage called builder using the base image golang:1.20. Copy the hello.go file into the container at /app/hello.go and set the working directory to /app. Add a command to build the Go program into a binary named hello.
Docker
Hint
Use FROM golang:1.20 AS builder to name the build stage. Use WORKDIR and COPY to prepare files. Use RUN go build -o hello hello.go to compile.
3
Add the final stage to copy the binary
In the same Dockerfile, add a final stage using the base image alpine:latest. Copy the compiled binary hello from the builder stage to /hello in the final image. Set the container to run /hello when started.
Docker
Hint
Use FROM alpine:latest for the final stage. Copy the binary with COPY --from=builder. Use CMD ["/hello"] to run the program.
4
Build and run the Docker image to see the output
Build the Docker image with the tag hello-multistage using the command docker build -t hello-multistage .. Then run the container with docker run --rm hello-multistage and observe the output.
Docker
Hint
Use docker build -t hello-multistage . to build and docker run --rm hello-multistage to run the container.
Practice
(1/5)
1. Why do multi-stage builds in Docker help reduce the final image size?
easy
A. Because they run containers faster
B. Because they use a single large base image for all stages
C. Because they copy only the necessary files from build stages to the final image
D. Because they install all dependencies in every stage
Solution
Step 1: Understand multi-stage build process
Multi-stage builds use multiple FROM statements to separate build and runtime environments.
Step 2: Identify file copying behavior
Only necessary artifacts are copied from build stages to the final image, excluding build tools and dependencies.
Final Answer:
Because they copy only the necessary files from build stages to the final image -> Option C
Quick Check:
Copying only needed files = smaller image [OK]
Hint: Remember: copy only what you need to keep image small [OK]
Common Mistakes:
Thinking all stages are combined fully
Assuming all dependencies stay in final image
Believing multi-stage builds speed up container runtime
2. Which of the following is the correct syntax to copy files from a previous stage named builder in a multi-stage Dockerfile?
easy
A. COPY --from=builder /app/build /app
B. COPY builder:/app/build /app
C. COPY /app/build builder:/app
D. COPY --stage=builder /app/build /app
Solution
Step 1: Recall Dockerfile COPY syntax for multi-stage
The correct syntax uses COPY --from=stageName source destination.
Step 2: Match syntax with options
COPY --from=builder /app/build /app matches the correct syntax exactly.
Final Answer:
COPY --from=builder /app/build /app -> Option A
Quick Check:
Use --from=stageName to copy files [OK]
Hint: Use COPY --from=stageName to copy files between stages [OK]
Common Mistakes:
Using incorrect flags like --stage
Trying to copy with colon syntax like builder:/path
Reversing source and destination paths
3. Given this Dockerfile snippet, what will be the size impact on the final image?
FROM node:18 AS builder
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
medium
A. The final image will be small because only the build output is copied
B. The final image will be empty because no files are copied
C. The final image will be large because it includes all node modules
D. The final image will include the entire node base image
Solution
Step 1: Analyze build and final stages
The builder stage installs node modules and builds the app. The final stage uses a lightweight nginx image.
Step 2: Check what is copied to final image
Only the build output folder /app/build is copied to nginx's html folder, excluding node modules and build tools.
Final Answer:
The final image will be small because only the build output is copied -> Option A
Quick Check:
Copying only build output reduces image size [OK]
Hint: Copy only build artifacts, not full build environment [OK]
Common Mistakes:
Assuming node modules are copied to final image
Thinking final image includes builder base image
Believing no files are copied at all
4. You wrote a multi-stage Dockerfile but the final image is unexpectedly large. Which mistake could cause this?
medium
A. Using a lightweight base image in the final stage
B. Using multiple FROM statements
C. Not naming the build stage
D. Copying the entire build directory including node_modules to the final stage
Solution
Step 1: Identify common causes of large final images
Copying unnecessary files like dependencies increases image size.
Step 2: Match mistake to options
Copying the entire build directory including node_modules to the final stage describes copying the entire build directory including node_modules, which bloats the image.
Final Answer:
Copying the entire build directory including node_modules to the final stage -> Option D
Quick Check:
Copying unneeded files causes large images [OK]
Hint: Avoid copying full build folders with dependencies [OK]
Common Mistakes:
Thinking multiple FROM statements cause large images
Believing missing stage names cause size issues
Assuming lightweight base images increase size
5. You want to build a Go application using multi-stage builds. The first stage compiles the app, and the second stage runs it. Which Dockerfile snippet best reduces the final image size?
hard
A. FROM golang:1.20
WORKDIR /app
COPY . .
RUN go build -o app
CMD ["./app"]
B. FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o app
FROM alpine
COPY --from=builder /app/app /app/app
CMD ["/app/app"]
C. FROM alpine
COPY . .
RUN go build -o app
CMD ["./app"]
D. FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o app
COPY . .
CMD ["./app"]
Solution
Step 1: Understand multi-stage build for Go app
Build the app in a full Go environment, then copy only the compiled binary to a small base image.
Step 2: Evaluate options for size reduction
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o app
FROM alpine
COPY --from=builder /app/app /app/app
CMD ["/app/app"] uses golang image to build, then copies only the binary to alpine, minimizing final image size.
Final Answer:
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o app
FROM alpine
COPY --from=builder /app/app /app/app
CMD ["/app/app"] -> Option B
Quick Check:
Build in full image, run in minimal image [OK]
Hint: Build in full image, copy only binary to small image [OK]
Common Mistakes:
Building and running in same large image
Trying to build in alpine without Go tools
Copying full source code to final image
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.