Docker Multi-stage builds optimize Dockerfiles while keeping them easy to read and maintain. I will share important nuggets about multi-stage builds using Dockerfile created for one of the previous blogs(containerizing ASP.NET Core Web API and deploying to AKS) as an example.
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY ["SampleWebApp/SampleWebApp.csproj", "."]
RUN dotnet restore "SampleWebApp.csproj"
COPY . .
RUN dotnet build "SampleWebApp.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "SampleWebApp.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "SampleWebApp.dll"]
The main points about this Dockerfile are
microsoft/dotnet:2.1-aspnetcore-runtime
is needed as base image for ASP.NET Core Web API- The Dockerfile has multiple
FROM
statements for multiple named stages e.g. first stage is named ‘base’ and last stage is named ‘final’. EachFROM
instruction can use a different base, and each of them begins a new stage of the build. - The ‘build’ stage builds the project using
microsoft/dotnet:2.1-sdk
. This container is later discarded by Docker as we don’t need SDK in final image. - The ‘final’ stage copies files from ‘publish’ stage on top of the ‘base’ layer
- The intermediate stages i.e. ‘build’, ‘publish’ etc. are discarded by Docker
If you execute docker build command build -t samplewebapp . --no-cache
, you will see in logs that intermediate containers are removed by Docker, which optimizes image size.
You can read more @ Use multi-stage builds
You can download code from GitHub