Multi-stage Build Explained Clearly
๐ 1. What Does FROM xxx AS builder Mean?
In Dockerfile,
FROM ubuntu:24.04 AS builder
defines a build stage called builder.
You typically use this stage to compile or package your application, and then later copy the final artifacts into a clean runtime image using:
COPY --from=builder /path/in/build /path/in/final
Only the last stage (or the one you specify with --target) becomes the final image โ all previous stages are discarded.
โ๏ธ 2. How It Works
- Each
FROMstarts a new build stage (a temporary image layer). AS builderassigns a name for later reference.- Only the final stage remains in the published image โ previous layers are used only during the build process.
๐ก 3. Benefits
- Smaller images โ build tools and headers stay out of the runtime.
- Improved security โ no compilers or dev tools in production.
- Cleaner separation โ build vs. run responsibilities are clear.
- Better caching โ build dependencies cached separately.
- Flexible workflows โ easily produce multiple targets or artifacts.
๐งฐ 4. Common Use Cases
- Building apps from source (e.g., Postfix, Nginx, Redis).
- Frontend builds (Node.js โ Nginx minimal runtime).
- Multi-artifact pipelines.
- Packaging
.debor.tar.gzfiles.
๐งฑ 5. Example: Building Postfix
# === Stage 1: Build ===
FROM ubuntu:24.04 AS builder
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ARG POSTFIX_VERSION=3.10.4
ARG POSTFIX_SRC_URL="https://archive.postfix.org/official/postfix-${POSTFIX_VERSION}.tar.gz"
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates curl build-essential pkg-config \
libssl-dev libsasl2-dev libmariadb-dev-compat libmariadb-dev \
liblmdb-dev zlib1g-dev m4 libpcre2-dev && rm -rf /var/lib/apt/lists/*
WORKDIR /usr/src
RUN curl -L "$POSTFIX_SRC_URL" -o postfix.tgz \
&& tar xzf postfix.tgz && cd postfix-* \
&& make -f Makefile.init makefiles CCARGS='-DUSE_TLS -DUSE_SASL_AUTH -DUSE_LMDB -DUSE_PCRE2 -DUSE_MYSQL' \
AUXLIBS='-lssl -lcrypto -lsasl2 -llmdb -lpcre2-8 -lz -lmariadb' \
&& make && mkdir -p /out && cp -r ./out/* /out/
# === Stage 2: Runtime ===
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates libsasl2-2 liblmdb0 zlib1g \
libpcre2-8-0 libmariadb3 libssl3 && rm -rf /var/lib/apt/lists/*
COPY --from=builder /out/ /
EXPOSE 25 587
CMD ["/usr/sbin/postfix", "start-fg"]
๐ The final image contains only the Postfix runtime, not the compilers or dev libraries.
๐ 6. Best Practices
- Keep builder and runtime base images consistent.
- Use
lddto verify runtime library dependencies. - Test build stage with
--target builder. - Run as non-root in production.
- Use BuildKit secrets to handle SSH keys or tokens securely.
โ Conclusion
FROM ... AS builder is the cornerstone of multi-stage builds โ
it lets you build in a โfatโ environment and ship a โslimโ runtime image.
The result: smaller, safer, and cleaner Docker images,
and a modern best-practice for all serious container projects.