dotnet-architecture / News

News on .NET Architecture Guidance, eShopOnContainers and all the reference apps in dotnet-architecture
MIT License
1.1k stars 79 forks source link

Docker multi-stage builds support in eShopOncontainers #5

Open CESARDELATORRE opened 6 years ago

CESARDELATORRE commented 6 years ago

In the last weeks we migrated to Docker Multi-Stage dockerfiles so the compilation of .NET projects and build of Docker images are created under a single Docker command (docker-compose build or docker build) and consistent across development environments (Windows, Mac, Linux) when using the CLI or Visual Studio.

What is a Docker multi-stage build?

Multi-stage builds are a new feature requiring Docker 17.05 or higher on the daemon and client. In Visual Studio, it is supported since version VS 2017 15.5 (December 2017) which is the same timeframe we migrated eShopOnContainers to it.

As explained by Docker, "with multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image".

From a practical point of view, it allows us to build the .NET application/microservice bits and build the Docker image in a single command like "docker-compose build", both tasks performed by the Docker engine. You don't even need to have all the dependencies installed on your machine in order to build the images because those dependencies (like NPM, Bower or even .NET Core SDK) are included within the ASPNETCore build image.

As you can see in the following code, when using a Docker multi-stage build, the dockerfile includes multiple build stages, so it compiles your .NET Core code and generates the bits with dotnet publish within a build image with the SDKs, then it'll create the final lean/light container image:

dockerfile

FROM microsoft/aspnetcore-build:2.0 AS build-env
WORKDIR /app

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

# copy everything else and build/publish the .NET app bits
COPY . ./
RUN dotnet publish -c Release -o out

# build runtime image
FROM microsoft/aspnetcore:2.0.3
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "myaspnetcoreapp.dll"]

Here's a similar example of a dockerfile from the eShopOnContainers Catalog microservice that also has dependencies on additional libraries that we are explicitly copying so the build cache is taken into account across multiple microservices.

Why are Docker multi-stage builds very convenient?

Previously (when docker multi-stage builds didn't exist), in eShopOnContainers we had to build the .NET application bits in the first place with dotnet publish, usually by using scripts like the following which are based on dotnet publish: Windows PowerShell: build-bits-simple.ps1 Mac Bash: build-bits.sh

A similar process is what Visual Studio 2017 does under the covers if not using docker multi-stage builds.

Those scripts are NOT needed anymore because the Docker multi-stage builds already build the .NET bits in the first stages by using the .NET Core SDK image. Then, it creates a lean/light image with just the base ASP.NET Core image and those custom bits.

Therefore and as a result of using Docker multi-stage builds, the build process is now greatly simplified as you just need to run the following Docker CLI commands (also used by Visual Studio, under the covers):

Note that if you just run docker-compose up it will detect that you don't have the images and it will build it, as well.

Updates in Wiki for Windows and Mac dev environment

The Wiki posts on how to build and run eShopOnContainers when using the CLI have been updated and greatly simplified thanks to Docker Multi-Stage builds. Check it our here and provide feedback!:

Setting the eShopOnContainers solution up in a Windows CLI environment (dotnet CLI, Docker CLI and VS Code)

Setting eShopOnContainer solution up in a Mac, VS for Mac or with CLI environment (dotnet CLI, Docker CLI and VS Code)

When using Visual Studio, the experience is similar, although, under the covers it is also using the same Docker multi-stage builds when the dockerfiles are using it.

Please, check this out and send us feedback either by answering this issue/news or by creating new issues at eShopOnContainers. Thanks= you! :)