How to Build Tiny Docker Images with Multi‑Stage Builds: A Step‑by‑Step Guide
This article explains why small Docker images matter, demonstrates the traditional Dockerfile approach, introduces the Builder Pattern with its drawbacks, and then shows how Docker's multi‑stage build feature can produce equally small images with far less complexity, complete with code examples.
1. Example Project
A very simple web application built with Angular and Node.js.
Try it yourself:
git clone https://github.com/bbachi/docker-multibuild-example.git
cd WebApp
npm run build
cd ..
npm start2. Building the Image with a Dockerfile
Steps:
Use node:10 as the base image.
Copy the source code.
Install Node.js and Angular dependencies.
Build the Angular UI.
Dockerfile:
FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./
COPY WebApp/package*.json ./WebApp/
RUN npm install \
&& cd WebApp \
&& npm install @angular/cli \
&& npm install
COPY . .
RUN cd WebApp && npm run build
EXPOSE 3070
ENTRYPOINT ["node"]
CMD ["index.js"]Build and run:
docker build -t nodewebapp:v1 .
docker run -it -d -p 3070:3070 nodewebapp:v13. Problems with the Conventional Build
Running docker images shows an image size of about 1.21 GB , which is unnecessarily large because it contains many unused files and dependencies.
4. Builder Pattern
The Builder Pattern uses two Dockerfiles: one for development (including all build tools) and one for production (containing only runtime files). A shell script dockerbuild.sh orchestrates three steps:
Build a full‑featured image from Dockerfile.dev.
Extract the necessary files from that image.
Build a lean production image from Dockerfile using the extracted files.
Example Dockerfile.dev (same as the previous Dockerfile) and production Dockerfile:
FROM node:10
WORKDIR /root/
COPY package*.json ./
COPY dist ./WebApp/dist
RUN npm install
COPY index.js .
EXPOSE 3070
ENTRYPOINT ["node"]
CMD ["index.js"]Script dockerbuild.sh:
#!/bin/sh
echo Building nodewebapp from Dockerfile.dev
docker build -t nodewebapp:v1 -f Dockerfile.dev .
echo Creating Container Out of Image
docker container create --name extract nodewebapp:v1
docker container cp extract:/usr/src/app/WebApp/dist ./dist
docker container rm -f extract
echo Building nodewebapp version 2
docker build --no-cache -t nodewebapp:v2 .
rm ./distRunning the script creates two images: v1 (development) and v2 (production). The production image is much smaller.
5. Drawbacks of the Builder Pattern
Requires maintaining two Dockerfiles and an extra shell script.
Produces two separate images.
Complex command chaining with && and backslashes can be error‑prone.
6. Multi‑Stage Build
Introduced in Docker 17.05, multi‑stage builds allow multiple FROM statements in a single Dockerfile, each representing a build stage.
Dockerfile example:
FROM node:10 AS ui-build
WORKDIR /usr/src/app
COPY WebApp/ ./WebApp/
RUN cd WebApp && npm install @angular/cli && npm install && npm run build
FROM node:10 AS server-build
WORKDIR /root/
COPY --from=ui-build /usr/src/app/WebApp/dist ./WebApp/dist
COPY package*.json ./
RUN npm install
COPY index.js .
EXPOSE 3070
ENTRYPOINT ["node"]
CMD ["index.js"]The resulting image is as small as the Builder Pattern output but with far less complexity.
7. Advantages of Multi‑Stage Builds
All logic resides in a single Dockerfile.
Uses --from to copy artifacts between stages, eliminating the need for intermediate images.
Reduces maintenance overhead and potential for errors.
Conclusion
Both the Builder Pattern and multi‑stage builds can produce small Docker images; multi‑stage builds are generally preferred because they simplify the workflow while achieving the same size reductions.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
