Cale
Cale

Reputation: 617

Why is multi step docker build better?

I have been updating our dotnet core application from dotnet 2.0 to 2.1 and I see that multi step dockerfiles are now suggested. I read that it is more efficent to build your app inside a container with the dotnet SDK and then copy to a different container with just the runtime. https://github.com/dotnet/announcements/issues/18

I am wondering why this would be better that how we did it with our 2.0 images which would be to run dotnet publish MySolution.sln -c Release -o ./obj/Docker/publish on our build server (dotnet 2.1 sdk is installed on it) and then do a single step build where we copy the build output to an image.

It is claimed to be simpler to do a multi step build, but it seems more complicated to me to copy over everything you need for a build, and then copy the results to another container.

Here is what the multi step Dockerfile looks like

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY myproject.csproj app/
RUN dotnet restore myproject.csproj
COPY . .
WORKDIR /src/Setting
RUN dotnet restore myproject.csproj
RUN dotnet build myproject.csproj -c Release -o /app

FROM build AS publish
RUN dotnet publish myproject.csproj -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "myproject.dll"]

vs a single step one.

FROM microsoft/aspnetcore:2.0
ARG source
WORKDIR /app
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "Myproject.dll"]

Any thoughts?

Upvotes: 0

Views: 206

Answers (2)

Cale
Cale

Reputation: 617

Ended up just using a single stage build because we can build the app on our CI server. The CI server has the SDK installed but our container just uses the runtime image. Building from the SDK image could be interesting if you don't have the dotnet sdk available, or you want to build on a container.

Here is what my Dockerfile looks like for 2.1:

FROM microsoft/dotnet:2.1-aspnetcore-runtime
WORKDIR /app
EXPOSE 80
COPY Microservices/FooService/Foo/obj/Docker/publish .
ENTRYPOINT ["dotnet", "Foo.dll"]

Upvotes: 0

Mohammed Noureldin
Mohammed Noureldin

Reputation: 16806

I read that it is more efficent to build your app inside a container with the dotnet SDK and then copy to a different container with just the runtime.

I believe that this description already exists before .Net Core 2.1 in the official documentation of Docker.

This is simply because you need SDK only to build your application, but if you have already built the application somewhere else, you can directly run it on runtime container (not SDK container). I did that a lot when no SDK were available for ARM processors, I had to build the application on my PC, then had to copy it to the target device. That was not that easy, because I always had dependencies problems, which I had to solve manually.

Therefore, it is almost always recommended to build the application on the machine you want to deploy the app on. This guaranties that your application will be build with the proper settings for that exact software and hardware requirements.

Because of that, I would always build the application on the target deploying device (on SDK container), and then copy the output of building to runtime container.

Now you are asking: why not simply run the application in SDK container? The only reason is probably because it will be significantly larger and heavier than any runtime container (as it has runtime environment + building tools).

Upvotes: 1

Related Questions