Last week I visited Docker con 2017 where Docker announced a whole lot of new features, under which a new feature in the docker build command, called multi staged builds.

These multi staged builds are extremely convenient to create images that are of minimum size. I am mostly using Docker on Windows, but this feature works on any version of Docker. When using Windows images, you might have noticed they are pretty large in size. Making your image as small as possible makes a big difference. So I will show you, based on the example I have used multiple times, how to create an optimized image to run an existing ASP.NET MVC 4.x on Windows Server Core.

To get started, you need Docker version 17.05.0-ce-rc1 or better. At the time of this writing I needed to install Docker for Windows Edge channel to make it work. Want to know which version you are running? run on the command line the following command: docker version or Docker –version

As you can find in my previous post, you can create a docker image, using your standard website publishing flow using web deploy. The docker file to make this work for the MVC musicstore sample is as follows:

Now with multi staged builds we will create a temporary image that does all the heavy lifting of installing the website using web deploy, but we will create a second stage where we create the actual image that we need. This image does not contain all the install files, webdeploy, the zip files, etc. We don’t need webdeploy when we run the website, so we are better of having a image that is clean and only contains the deployed files. this is not only better for image size, it also reduced your attac surface, which is a good practice if it comes to security as well!

The way we create a second stage is by adding the AS keyword at your first FROM statement. You can now create multiple FROM statements in your Dockerfile and only the last FROM is the actual image you want to create and publish. You can in your dockerfile now refer to any of the itnermediate stages by using the COPY keyword and there pass in the flag –from=[nameofstage].  So we can copy resutls from previous stages into our final image. See below the altered dockerbuild file that has two stages:

This now results in a bare minimum image that has microsoft/aspnet base image that is created by microsoft, and only contains files we need at runtime, that come from the previous step.

This simple example, only works of course if you install at the default website with default settings of the website and application pool. In case you still need to make changes, then you need to run the IIS commands to change the app pool settings in the final stage. But as you can see the result is a much cleaner and smaller image.

If you compare the two images then you see the image size differs with 315MB!

Also, the number of layers is drastically reduced. If you compare the image details, using Docker image inspect command you will see the number of layers for the first single stage build containers is 20 and for the multistage build the number of layers is only 5!

So multi stage builds are a big improvement if it comes to building efficient images. for me this will definitely be the way I build my images in the future!