Dockerfile: Optimize image size with multi-stage build

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’. Each FROM 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

Leave a Reply

Your email address will not be published. Required fields are marked *