Home > Blockchain >  Order of stages in Dockerfile for .NET Core
Order of stages in Dockerfile for .NET Core

Time:04-01

Being fairly new to Docker, I'm currently reading several tutorials and there are two things I don't really understand. According to the official Docker documentation, the Dockerfile could look like this:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# Copy everything else and build
COPY ../engine/examples ./
RUN dotnet publish -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "aspnetapp.dll"]

The first stage is to import the sdk and the second is to import the dotnet runtime. However, in other tutorials, e.g. this one from Jetbrains, the order is reversed; first the runtime is imported and subsequently the sdk is imported.

First question; is there a preferred order of the imports (and why)?

Second question, in the example above, the csproj is first copied, dotnet restore is run, and then all other files are copied before building the application. Why not just copy everything at once?

CodePudding user response:

The way they're structured has a lot to do with maximizing the use of cached layers from previous builds to make the build go faster and using a runtime base image that's smaller that a full SDK image.

If you don't care about the build speed and image size, you can do something really simple like

FROM mcr.microsoft.com/dotnet/sdk:6.0
WORKDIR /src
COPY . .
RUN dotnet publish -o out
WORKDIR /src/out
ENTRYPOINT ["dotnet", "aspnetapp.dll"]

This Dockerfile will have to build everything every time you change a file. You can speed up the restore of Nuget packages by realising that you rarely change the .csproj file.

FROM mcr.microsoft.com/dotnet/sdk:6.0
WORKDIR /src
COPY aspnetapp.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -o out
WORKDIR /src/out
ENTRYPOINT ["dotnet", "aspnetapp.dll"]

Now when you just change some code (but not the .csproj file), Docker will see that up until COPY . . everything is the same as when you last ran docker build, so it'll just take the layers from the cache and you won't have to actually run the dotnet restore saving you some time.

To save some space on the final image, we can use the aspnet image as the base, rather than the sdk image. To do that we can use a multistage Dockerfile and copy files from the first stage to the last (and final) stage like this

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY aspnetapp.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -o out

FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build /src/out /app
ENTRYPOINT ["dotnet", "aspnetapp.dll"]

Now the final image is smaller, so it takes up fewer resources when we run it.

  • Related