This post is originally published as article within SDN Magazine on October 13th, 2017.

During the past year I supported several clients in their journey toward Containerized Delivery on the Microsoft stack. In this blogseries I’d like to share eight practices I learned while practicing Containerized Delivery on the Microsoft stack using Docker, both in a Greenfield and in a Brownfield situation. In the second blogpost of this series I want to talk about
Multi-stage builds.

PRACTICE 2: Multi-stage builds

New since Docker 17.05 is the concept of multi-stage builds. As described in the previous practice, container images can be rather large because of a large number of image layers. Multi-stage builds help you to reduce the size of your images in an easy way. Instead of an image that contains all in-between image-layers, the multi-stage build implementation makes it possible to copy resulting image content of a given image into another image you define.
Another great benefit of the multi-stage build is that it minimizes your attack surface by removing all in-between layers and installations. And last but not least, multi-stage builds enable easy creation of debug and testing images from your production images by putting the resulting content of your production image into a default debugging and testing image.

Before Docker 17.05 this could also be achieved by making use of the Docker builder-pattern . In the new multi-stage solution we can just add a second FROM statement to our existing Docker file and instruct that image to copy the content of the earlier stage into the image of this second stage by making use of the –from argument within the COPY instruction. As shown in the following example, the content of the first image definition (called temp) is copied into the second image definition (called final). As a result, the image size of the final image is 315 MB smaller than the original temp image! Looking at the number of image layers, we see a reduction of 15 out of 20 image layers!

## First Stage – Install WebDeploy, create disk structure, deploy MVCMusicStore website
FROM microsoft/aspnet AS temp
RUN mkdir c:install c:MvcMusicstore
ADD WebDeploy_2_10_amd64_en-US.msi /install/WebDeploy_2_10_amd64_en-US.msi
WORKDIR /install
RUN msiexec.exe /i c:installWebDeploy_2_10_amd64_en-US.msi /qn
WORKDIR /MvcMusicStore
ADD fixAcls.ps1 /MvcMusicStore/fixAcls.ps1
ADD /MvcMusicStore/
ADD MvcMusicStore.deploy.cmd /MvcMusicStore/MvcMusicStore.deploy.cmd
ADD MvcMusicStore.SetParameters.xml /MvcMusicStore/MvcMusicStore.SetParameters.xml
RUN powershell.exe -executionpolicy bypass .fixAcls.ps1
RUN MvcMusicStore.deploy.cmd, /Y

## Second Stage - Creates final image
FROM microsoft/aspnet AS final
COPY --from=temp c:/inetpub/wwwroot c:/inetpub/wwwroot

Interested in the next practice? See PRACTICE 3: Keep your Windows containers up-to-date.