.NET Core Application in Docker
Disclaimer: Currently I am employed by Microsoft, but my views and thoughts are still my own. The reason I joined Microsoft was, the work Microsoft have been doing for last couple of years in Open Source Space. Today I am a advocate for Open Source representing Microsoft.
[ToC]
As the time goes, any popular technology is adopted by vendors. As such, Microsoft has adopted Docker as it now de-facto container platform, over its own Service Fabric. Both .NET Framework and .NET Core can be packaged inside a Docker container.
.NET Framework is has best performance inside a Windows container, which is still a preview in Azure Kubernetes Services. You can use Linux container for .NET Framework application by running it on top of Mono runtime, but the performance and compatibility might lack in some cases.
.NET Core on other hand is natively cross-platform. You can utilize official (well Mono is now also part of .NET Foundation, and official) .NET Core runtime in a Linux container.
Prerequisites
If you are not fully familiar with Docker, please consider reading my other posts on Docker:
In order to package and run a .NET Core application you will need:
- .NET Core SDK
- Docker
.NET Core Application
Create new application
To make it easier, I am just going to use the scaffolded Hello World console application. You can create a simple Hello World console application by:
dotnet new console --name hello
Note: dotnet-cli uses the current directory name as the project name. You can override it with
--name <project name>
argument.
Test the application
It is always a good idea to test the application, before we try to containerize it, just to make sure the application is working. If there is a problem down the road, we know it is with the container and not the application itself.
We can simply do a quick test by running the applications:
dotnet run
It should show a output like this:
Hello World!
Now that we know the application works, we can try to containerize it.
Note: When you run the project dotnet-cli will run
dotnet restore
anddotnet build
before running the project.
Publish the project
When you publish the project, dotnet-cli will build the project an publish the output along with the any needed dependencies.
You can publish the project with:
dotnet publish -c Release
The argument -c Release
makes sure that dotnet-cli will build the project in Release profile, without any Debug Symbols.
The main executable for this project will be hello.dll
. dotnet-cli outputs by default a <project name>.dll
, this can be overridden by configuring the .csproj
file for the project.
dotnet-cli will publish the output to bin/Release/netcoreapp3.1/publish/
directory by default, this can be overridden by --output <directory>
argument.
Note: Just like with
dotnet run
, when you publish the project dotnet-cli will rundotnet restore
anddotnet build
before published the project.
Docker
Create a DockerFile
Docker needs a docker file in order to build images and run these images in container. Dockerfile defines, how the image is build and how the content in the image can be executed.
We can simply create an empty file by:
On Windows
type nul > Dockerfile
On POSIX (Linux and macOS)
touch Dockerfile
Dockerfile
content
Paste the following into the the newly created Dockerfile
.
Note: Make sure to use the same runtime version as the SDK you have installed on your develpoment host.
FROM mcr.microsoft.com/dotnet/core/runtime:3.1
COPY bin/Release/netcoreapp3.1/publish/ App/
WORKDIR /App
ENTRYPOINT ["dotnet", "hello.dll"]
FROM
tells the Docker to which base image to use. I am using a prebuilt .NET Core Runtime version 3.1.
COPY
tells the Docker to copy content from the host to the image.
WORKDIR
tells the Docker to switch to /App
directory in the image. It is similar to cd
command.
ENTRYPOINT
tells Docker what to execute. In this we want to execute dotnet
with the argument hello.dll
, where hello.dll
is compiled output's main executable.
Build the image
TO be able to use the image, we need to first build it.
docker build -t hello -f Dockerfile .
-t hello
tells Docker to name the image with the name hello
, so that it is easier to reference later on.
-f Dockerfile
tells the Docker to use the Dockerfile
as the build file. You can have several Dockerfiles in a single project, i.e. one for development and another for production.
Lastly .
(the dot) tells the Docker to use current directory as the working directory. This is important if you are using the relative paths in the Dockerfile
.
When we list all the images we can see the image was built:
docker images
The output will show you both the image you created, and the base image Docker downloaded to build your image.
REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest 391bf79979b3 8 minutes ago 327MB
mcr.microsoft.com/dotnet/core/runtime 3.1 b66ce51a57d5 3 weeks ago 327MB
Run the container
Now that was have a container image ready, we can create and run the container.
You can run the container with:
docker run -ti hello
-ti
tells the Docker to run the container in TTY and interactive mode. You can use -d
for running the application in background.
hello
is the name of the image we want to run.
You should have a output like this:
Hello World!
tl;dr
As you can see it is very easy to run a .NET Core application inside a Docker container.
Keep in mind this post just highlights very quickly basic of how to run a Console application in Docker.