Multistage Docker | Highly optimized docker image

Suneet Bansal
3 min readDec 21, 2023

--

Docker multistage build helps to optimize the overall image size. In multistage build, Dockerfile have multiple From and output of one From becomes input to the next From and so on. In this way you forget what you install as dependencies for example for stage 1 and pass only what you want to keep in next stage.

Docker multistage build helps to optimize the overall image size and also other advantages.

In multistage build, Dockerfile could have multiple From and output of one From becomes input to the next From and so on. In this way you forget what you installed as dependencies for example in stage 1 and pass only what you want to keep in next stage.

Lets take an example without using Multistage concept and will analyze the image size

Assuming you have below kind of Project structure -

Where web folder contains the build in dist folder and server folder contains start command which run your web application on 3300 port.

Below is the Dockerfile you created who will install dependencies for web and server both and then run your web application using npm run start command.

FROM node

WORKDIR /app

COPY . .

WORKDIR /app/web

RUN npm install

WORKDIR /app/server

RUN npm install

CMD ["sh", "-c", "npm run start"]

To build and run, you will run below commands -

docker build -t web:1 .
docker run -p "3300:3300" web:1

Now lets check the image since by running below command -

docker images 

You will get size as 1.47 GB

Now lets try to optimize image size by converting Dockerfile to Multistage Dockerfile-

Note — All the other folders in your project will remain same, only Dockerfile would be change.

#Stage 1
FROM node as build

WORKDIR /app
COPY . .
WORKDIR /app/web

RUN npm install
RUN npm run build

# Stage 2
FROM node
COPY --from=build /app/web/dist /app/server
COPY --from=build /app/server /app/server

WORKDIR /app/server
RUN npm install

CMD ["sh", "-c", "npm run start"]

In above Dockerfile, you will see that we have 2 FROM statements.

First FROM -> Stage 1

  1. We are installing dependencies for web and making the build. Once build is created, node_modules won’t be needed so we will only copy the dist to the next Stage.
  2. You will also notice that we provided the alias as “build” to Stage 1 because we would need it in next Stage.

Second FROM -> Stage 2-

  1. Copy only dist which was created in Stage 1 and left all other files including node_modules of web folder.
  2. Also copy content of server folder
  3. install dependencies of server
  4. run the server using npm run start command.

Note: “--from=build” is used to picking the content from previous stage.

To build and run, you will run below commands -

docker build -t web:1 .
docker run -p "3300:3300" web:1

Now lets check the image since by running below command -

docker images

You will get size as 1.11 GB

Conclusion

Image size with non Multistage Docker approach was — 1.47 GB

Image size with Multistage Docker approach is — 1.11 GB

So the total reduction of Image size is 0.36 GB (~25% reduction is image size)

I hope this article would help you to effectively use Multistage Docker approach to further optimize your image size.

Stay tuned and subscribe to my Medium Channel!!!

Thanks!!!

--

--