📖 Scenario: You want to create a small, efficient Docker image to serve a static website using nginx. To keep the image size small, you will use a multi-stage build. The first stage will build the static site files, and the second stage will use nginx to serve those files.
🎯 Goal: Build a Dockerfile with two stages: one to prepare the static site files and one to serve them with nginx. The final image should only contain the nginx server and the static files.
📋 What You'll Learn
Create a first stage named builder using the alpine image
Add a directory /app in the builder stage and create an index.html file with exact content
Create a second stage using the nginx:alpine image
Copy the index.html file from the builder stage to the /usr/share/nginx/html directory in the second stage
Expose port 80 and set the default command to run nginx
💡 Why This Matters
🌍 Real World
Multi-stage builds are used to optimize Docker images by separating build and runtime environments. This is common in deploying static websites and web applications.
💼 Career
Understanding multi-stage builds helps you create efficient container images, a key skill for DevOps engineers and developers working with Docker and cloud deployments.
Progress0 / 4 steps
1
Create the builder stage with static site files
Create the first stage named builder using the alpine image. Inside this stage, create a directory /app and add a file named index.html with the exact content: <h1>Welcome to My Static Site</h1>.
Nginx
Hint
Use FROM alpine AS builder to start the first stage. Use RUN mkdir /app to create the directory. Use RUN echo '...' > /app/index.html to create the file with content.
2
Add the nginx stage and copy static files
Create the second stage using the nginx:alpine image. Copy the index.html file from the /app directory in the builder stage to the /usr/share/nginx/html directory in this stage.
Nginx
Hint
Use FROM nginx:alpine to start the second stage. Use COPY --from=builder /app/index.html /usr/share/nginx/html/index.html to copy the file.
3
Expose port 80 and set default command
In the nginx stage, add a line to expose port 80. Then set the default command to run nginx in the foreground using CMD ["nginx", "-g", "daemon off;"].
Nginx
Hint
Use EXPOSE 80 to open port 80. Use CMD ["nginx", "-g", "daemon off;"] to run nginx in the foreground.
4
Build and run the multi-stage Docker image
Build the Docker image with the tag static-site using the Dockerfile. Then run a container from this image mapping port 8080 on your machine to port 80 in the container. Finally, print the command to check the container logs.
Nginx
Hint
Use docker build -t static-site . to build the image. Use docker run -d -p 8080:80 static-site to run the container. Use docker logs <container_id> to check logs.
Practice
(1/5)
1. What is the main benefit of using multi-stage builds for static sites with nginx?
easy
A. It automatically updates static files without rebuilding the image.
B. It allows running multiple nginx servers in one container.
C. It reduces the final image size by separating build and serve stages.
D. It enables dynamic content generation inside the nginx container.
Solution
Step 1: Understand multi-stage build purpose
Multi-stage builds separate the build process from the final image, so only necessary files are included.
Step 2: Identify benefits for static sites
This separation reduces the final image size and improves security by excluding build tools from the runtime image.
Final Answer:
It reduces the final image size by separating build and serve stages. -> Option C
Quick Check:
Multi-stage builds = smaller images [OK]
Hint: Remember: build tools stay out of final image for smaller size [OK]
Common Mistakes:
Thinking multi-stage runs multiple nginx servers
Believing static files update automatically without rebuild
Confusing static site builds with dynamic content generation
2. Which Dockerfile snippet correctly copies static files from a builder stage to the nginx stage?
easy
A. COPY --to=builder /app/dist /usr/share/nginx/html
B. COPY /app/dist /usr/share/nginx/html --from=builder
C. COPY /usr/share/nginx/html /app/dist --from=builder
D. COPY --from=builder /app/dist /usr/share/nginx/html
Solution
Step 1: Recall correct COPY syntax for multi-stage
The syntax is COPY --from=stage source_path destination_path.
Step 2: Match snippet to syntax
COPY --from=builder /app/dist /usr/share/nginx/html uses COPY --from=builder /app/dist /usr/share/nginx/html which is correct.
Final Answer:
COPY --from=builder /app/dist /usr/share/nginx/html -> Option D
Quick Check:
COPY --from=stage source dest = correct [OK]
Hint: COPY uses --from=stage before source path [OK]
Common Mistakes:
Placing --from after paths
Using --to instead of --from
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 . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
medium
A. Final image will be small because only nginx and static files are included.
B. Final image will be empty because build files are not copied.
C. Final image will be large because node is included.
D. Final image will contain both node and nginx layers.
Solution
Step 1: Analyze multi-stage build layers
The builder stage uses node to build files, but the final stage uses nginx:alpine only.
Step 2: Understand what is copied to final image
Only the /app/dist folder from builder is copied into nginx image, so node and build tools are excluded.
Final Answer:
Final image will be small because only nginx and static files are included. -> Option A