This short post introduces the concept of multi-stage Docker builds for ASP.NET Core applications.
Microsoft maintains two asp.net core images on Docker hub. The following are descriptions from the Docker hub pages:
This repository contains images that are used to compile/publish ASP.NET Core applications inside the container. This is different to compiling an ASP.NET Core application and then adding the compiled output to an image, which is what you would do when using the microsoft/aspnetcore image. These Dockerfiles use the microsoft/dotnet image as its base.
This repository contains images for running published ASP.NET Core applications. These images use the microsoft/dotnet image as its base. These images contain the runtime only. Use
microsoft/aspnetcore-buildto build ASP.NET Core apps inside the container.
Before multi-stage builds there were basically 2 options. The first option was to install the SDK on your computer or CI machine, build and package your app then build a container based on the ASP.NET Core runtime and package output. The second option was to use a container with the SDK already baked in, mount that container to a volume on your host, build and publish your app to that volume and finally, build a container based on the ASP.NET Core runtime and package output.
Multi-stage builds allow developers to build their ASP.NET core projects in aspnetcore-build and copy the published output to an aspnetcore container in one Docker file without unnecessarily increasing the size of the final container. The following Docker file was taken from one of my Github projects.
FROM microsoft/aspnetcore-build:2.0.0-preview2 as builder COPY . /workspace WORKDIR /workspace RUN mkdir /publish RUN dotnet publish -o /publish src/aspnet-core-sample/aspnet-core-sample.csproj FROM microsoft/aspnetcore:2.0.0-preview2 EXPOSE 80/tcp COPY --from=builder /publish /app WORKDIR /app ENTRYPOINT ["dotnet", "aspnet-core-sample.dll"]
A multi-stage build Docker file is simply a Docker file containing multiple FROM clauses. Each FROM clause is referred to as a stage. Traditionally, these stages would have been separate Docker files. This feature allows you to chain multiple steps in the image build process without complex glue scripts and CI processes.