Module 09 / Project 02 — Multi-Stage Build¶
Home: README
Learn Your Way¶
| Read | Build | Watch | Test | Review | Visualize | Try |
|---|---|---|---|---|---|---|
| — | This project | — | — | Flashcards | — | — |
Focus¶
Multi-stage Docker builds to reduce image size, and .dockerignore to exclude unnecessary files.
Why this project exists¶
A single-stage Dockerfile works, but the resulting image is larger than necessary because it includes build tools (pip, setuptools, wheel) that are only needed during installation. Multi-stage builds split the process into a "builder" stage that installs dependencies and a "production" stage that copies only the final artifacts. The result is a smaller, more secure image with a reduced attack surface.
Run¶
Build both images for comparison¶
cd projects/modules/09-docker-deployment/02-multi-stage-build
# Build the single-stage image
docker build -f Dockerfile.simple -t single-stage-app .
# Build the multi-stage image
docker build -t multi-stage-app .
Compare image sizes¶
You should see the multi-stage image is noticeably smaller. The exact difference depends on your system, but expect 20-50 MB savings.
Run the multi-stage image¶
Visit http://127.0.0.1:8000 to verify it works.
Expected output¶
Both images produce the same API response:
The docker images comparison shows something like:
(Your sizes will vary. The point is the multi-stage image is smaller.)
Alter it¶
- Add a third stage to the Dockerfile that runs tests before building the production image. (Hint: add a "test" stage between builder and production that runs
python -c "import fastapi; print('OK')") - Remove
.git/from.dockerignoretemporarily. Rebuild both images and compare sizes. Add it back. - Add a
LABELinstruction to the production stage with your name and the build date.
Break it¶
- In the multi-stage Dockerfile, change
COPY --from=builder /build/.venv /app/.venvtoCOPY --from=builder /build/.venv /wrong/path. Rebuild and run. What error do you get? - Remove the
ENV PATHline in the production stage. Rebuild and run. What happens when uvicorn tries to start? - Delete the
.dockerignorefile and rebuild. Is the image larger? Check withdocker images.
Fix it¶
- Restore the correct path
/app/.venv. The virtual environment must be where the PATH expects it. - Restore the
ENV PATHline. Without it, the shell cannot finduvicornor any installed packages. - Restore the
.dockerignorefile. Without it, Docker copies everything (including.git/,__pycache__/, and local.venv/) into the build context.
Explain it¶
- What is a "stage" in a multi-stage build? How many stages does our Dockerfile have?
- Why do we create a virtual environment in the builder stage instead of installing packages globally?
- What does
COPY --from=builderdo? How is it different from a regularCOPY? - What is the purpose of
.dockerignore? How is it similar to.gitignore?
Mastery check¶
You can move on when you can:
- explain why multi-stage builds produce smaller images,
- write a multi-stage Dockerfile from scratch,
- create a
.dockerignorefile with appropriate exclusions, - describe what
COPY --from=<stage>does.
Related Concepts¶
Next¶
Continue to 03-docker-compose.