Skip to content
← DevOps foundations

Learning bite

Multi-stage builds and runtime boundaries

Separate build tools from runtime needs and verify what the final image actually contains.

Documentation reviewed2026-10-01 · 3 min read
On this page

Build tools and runtime tools serve different jobs

A frontend may need Node to compile browser files but only a file server to serve the result. A Java service needs a compiler during a build and a compatible runtime afterward. Python dependencies may need compilation tools even when the running service does not. A multi-stage Dockerfile lets one stage produce files and another stage copy only what it needs.

This can reduce unnecessary runtime contents, but small is not synonymous with correct or secure. Native libraries, certificates, writable paths, runtime user, and architecture still matter. A minimal image without a shell also changes how you troubleshoot it.

Try the transfer with a deliberately small example

Create a new docker-stages directory so the earlier fixture remains intact. Save Dockerfile:

dockerfile
FROM python:3.12-slim AS build
WORKDIR /build
RUN python -c 'from pathlib import Path; Path("status.json").write_text("{\"status\":\"ok\"}\n")'

FROM python:3.12-slim AS runtime
WORKDIR /app
COPY --from=build /build/status.json ./status.json
USER 10001:10001
EXPOSE 8000
CMD ["python", "-m", "http.server", "8000", "--bind", "0.0.0.0"]

The first stage generates a file. The second starts from a fresh base and copies that one output from the named stage. It does not inherit every file in the first stage. Both stages deliberately use Python here so you can learn the transfer without another compiler or dependency manager; this example makes no image-size reduction claim.

From this directory:

bash
docker build -t learnwithsk-stages:dev .
docker run --rm learnwithsk-stages:dev python -c 'from pathlib import Path; print(Path("/app/status.json").read_text(), end=""); print(Path("/build").exists())'

Expected output is the ok JSON and then False. The final image has the copied file at /app/status.json, not the build stage's /build directory. This command overrides the default server command to inspect the runtime filesystem.

Run the default command with a temporary loopback port mapping, request status.json, then stop and remove only this fixture. You can use the same docker run --rm --name ... -p 127.0.0.1:8765:8000 ... pattern after confirming the earlier server is stopped. Remove learnwithsk-stages:dev when finished.

Read the final process settings

CMD provides the default command or default arguments; ENTRYPOINT can define the executable they accompany. For an image with ENTRYPOINT ["python", "tool.py"] and CMD ["--help"], default execution runs python tool.py --help; arguments after the image name replace the default CMD arguments. --entrypoint explicitly overrides the entrypoint.

Exec-form arrays avoid an extra shell and help the main process receive signals directly. They do not solve every shutdown problem: the application still needs to handle termination and child processes appropriately. A shell wrapper that fails to use exec may become the process receiving shutdown instead of the application.

Apply the idea to a real service

For each MicroBank service, write a table of build inputs, build-only tools, files copied to runtime, runtime command, user, port, and writable directories. Verify native dependencies and target architecture rather than choosing an image solely by size. Keep credentials, state, .local/, and private evidence out of the build context.

Checkpoint: why is copying only the binary sometimes insufficient? It may depend on runtime libraries, configuration, certificates, or files not embedded in it. Why must the final stage be tested? A successful compilation proves less than a successful runtime operation.

Next, use the Compose lab to observe the complete local lifecycle before moving to CI/CD and the guided MicroBank profile.

References: multi-stage builds↗, Dockerfile command behavior↗, context and dockerignore↗, and cache invalidation↗.

Your notes and evidence

Record observations, questions, or links to your work. Keep credentials out of your notes.

Loading saved progress…

Back up or restore this path

Progress and notes stay in this browser. A backup contains only this learning path.