Containerize A .NET Core App in 5 Minutes
.NET Core has enabled .NET developers to build applications that can run on virtually anything – Windows, Linux, and Mac OS. .NET Core then has found many uses among including many that overlap with workloads that lend themselves to containers such as daemons and web services. Combined with a package infrastructure, .NET Core applications can now be containerized rather quickly with a few simple commands.
The all important file in a .NET Core application is the project file, which not only tells the .NET Core run time what kind of project is running, but also contain a list of packages that are used by the Project. The .NET command line utility can read this file and download and install packages from Nuget, then build an application.
The most efficient way to build .NET Core apps is to use a muti-stage build with Docker. A typical build in Docker adds a new layer in the file system for each command found in a Dockerfile, so if a Dockerfile contains both build and release mechanism, all these layers are carried along through the life of the image. A multi-stage build though allows the results of one build be copied into a new image stack and leave behind any unecessary layers. Think of this like concrete building: if you want to build the second floor, you first need to build the first floor. You then set up scaffolding to support the second floor until it is hardened, and you remove the scaffolding. In this analogy, the scaffolding is the build environment and the floor is the output. A single stage build is essentially leaving the scaffolding and the floor while a multi-stage build is keeping floor without the scaffolding.
So to create multistage build, you first need to create a Dockerfile in the root of your project. The Dockerfile below is for a .NET Core app of sort. It takes the .NET Core and compiles it in the Builder container, then the output of the the Builder is copied from the Final Build container. Note the –from=0. This is the directive that copies the files between the containers. None of the source code is moved, just the binaries.
#Builder FROM microsoft/dotnet:1.1.2-sdk-jessie COPY /myapp /myapp RUN dotnet restore ./myapp && \ dotnet build -c release ./myapp && \ dotnet publish -c release -o pubdir ./myapp #Final Build FROM microsoft/dotnet:1.1.2-runtime COPY --from=0 /myapp/pubdir /myapp ENV ASPNETCORE_URLS http://+:80 ENTRYPOINT ["dotnet", "/myapp/myapp.dll"] EXPOSE 80
Notice that the Dockerfile is using an SDK image for the Builder too and the Final Build is using a runtime image. The difference here is that one of these contains the compiler and the other does not. More complex builds are possible with Docker and Multistage builds.
You can now build the image with Docker build.
docker build --tag yourtag .
You will see the output as it works through each of the stages of the build.