Docker Multi-Stage Build in Detail

Koushik Dutta
Dev Genius
Published in
4 min readMar 2, 2024

--

Multi-stage builds are great when you need to create an artifact or binary. Building such requires a lot of dependencies. However, once the binary is built, you don’t need the dependencies to run it.

You should consider using Docker multi-stage builds when your application has a complex build process and several dependencies or when you want to separate the build and runtime environments.

Why use Docker multi-stage build?

Here are some benefits of using Docker multi-stage build:

  • Generated images are smaller. The final image is typically much smaller than the one produced by a normal build, as the resulting image includes just what the application needs to run.
  • More secure containers. Packages and dependencies need to be kept up to date because they can be a potential source of vulnerability for attackers to exploit. Therefore, you should only keep the required dependencies. Using Docker multi-stage build means the resulting container will be more secure because your final image includes only what it needs to run the application.
  • Faster deployment. Smaller images mean less time to transfer or quicker CI/CD builds, faster deployment time, and improved performance.

Let’s Create A Single Stage Dockerfile App First

FROM node:16-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
docker build -t single-stage-build .

This is a normal or single-stage Dockerfile. When you run the docker build command, it will launch a build process starting with the base image. The resulting image will contain the build tools and the source code, the runtime environment that includes the dependencies to run your application, and libraries, but not all of these are needed in the final image for the application to run.

Now let’s check the memory of the image

Now let’s run the container

docker run -d -p 3000:3000 single-stage-build

So we can see the size of the image is 420 MB and it is quite huge.

Restructure the Dockerfile for multi-stage builds

You don’t need a Docker image of 420MB for a small application used here. So, how can you ensure you’re building optimal Docker images containing just what your application needs to run?

As the next step, restructure the Dockerfile to have multiple stages by replacing the content of the existing Dockerfile with the code provided below:

FROM node:16-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Second stage - Serve the application

FROM nginx:alpine
COPY --from=build /usr/src/app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

The Dockerfile now has two stages or steps (characterized by the FROM statements). This will create a two-stage build process: the first stage builds the React application, and the second stage will serve the built application using Nginx. The COPY command in the second stage copies the contents of the build directory from the first stage (alias "build") into the Nginx web server default directory. This sets up Nginx to serve your React application.

Build a Docker image with multi-stage builds

Now run the docker build command with the updated Dockerfile.

docker build -t multi-stage-build .

You can see that the final image has been reduced to just 43.2MB. That’s a lot less than the initial image. Now confirm that the application still gets displayed or works as it should be spinning up a container with the new image.

Why multi-stage build is smaller in size

A Multi-stage build consists of more than 1 FROM statement. When you have a second FROM statement in a Dockerfile, everything up until that statement is no longer part of the image, including ENV statements. In the above Dockerfile, when we finished building our App we copied the file to the /usr/share/nginx/html directory and exposed it via nginx. Thus we are discarding the previous react stages, ending up with a smaller image size.

For any type of help regarding learning Data Engineering, discussing cloud apps, or knowing more about the latest data engineering trends and technologies reach out to me at BhootNath.

P.S: I don’t charge money

--

--

Lead Data Engineer @Deloitte, Himalayan Off-beat Traveller , Follow Buddhism .