How to use multi-stage Docker builds

Ministry of Justice Digital & Technology
Just Tech
Published in
3 min readJul 26, 2019

--

by Tom Withers (Software Development Profession)

Photo by Guillaume Bolduc on Unsplash

Docker has revolutionized the way software engineers build applications; small maintainable pieces of software that can be easily scaled to meet demand. But with new technology, there are now more things to take into consideration. One such issue that arose with Docker is image size. Traditionally, to get an efficient docker image, you would use some complex shell commands within the Dockerfile to keep the layers as small as possible.

In Docker 17.05, multi-stage builds were introduced and this means we can now make docker images even smaller. Below, I’m going to go over an example of how to do this with a Symfony app and composer.

With multi-stage builds, you can use multiple FROM commands within a single Dockerfile. Each FROM command can use a different base and symbolises a new stage in the build. The most useful thing is that you can selectively copy artefacts from one stage to another leaving everything that you don’t need behind.

So let’s create a new Dockerfile and add our first FROM command. This will be using composer as a base image, so we can get all of our composer dependencies. We can also name the different stages within the build by adding AS <NAME> to the FROM command.

FROM composer AS composer

Now let’s copy over our composer.json and composer.lock files. We’re also going to add a RUN command, which will run a composer install.

FROM composer AS composerCOPY composer.json /appCOPY composer.lock /appRUN composer install

So the first part of our multi-stage build is done, this will allow us to install our composer dependencies into the first image and then copy them across into the final image.

Next, we need to build our final stage:

FROM php:7-fpm-alpineWORKDIR /var/wwwCOPY ./ /appCOPY — from=composer /app/vendor /app/vendor

Here, we start a new build using php7-fpm-alpine as the base image, then we use COPY to copy over the vendor folder into our new image. We leave all the composer gubbins behind, and it’s not saved into our final image.

The full Dockerfile looks like this:

FROM composer AS composerCOPY composer.json /appCOPY composer.lock /appRUN composer installFROM php:7-fpm-alpineWORKDIR /var/wwwCOPY ./ /appCOPY — from=composer /app/vendor /app/vendor

You only need a single Dockerfile. Just run docker build and docker the build process will start.

The end result of using multi-stage builds is a slim production-ready image without any complexity. I hope you can see the benefits of using multi-stage builds and I would definitely encourage you to try them out!

If you enjoyed this article, please feel free to hit the👏 clap button and leave a response below. You also can follow us on Twitter, read our other blog or check us out on LinkedIn.

If you’d like to come and work with us, please check current vacancies on our job board!

--

--

Ministry of Justice Digital & Technology
Just Tech

We design, build and support user-centred digital and technology services for the justice system.