Get Started With .NET Core on Docker
New .NET Core is the biggest change since the invention of .NET platform. It is fully open-source, componentised and is supported by Windows, Linux and Mac OSX. In this post I am going to give it a test ride by creating a containerized C# appliction with the latest .NET CORE CLI tool. I want to get a feel of how this experience is close to working with node.js or ruby.
Enviroment
Instead of installing .NET Core and CLI tool locally, I am going to use a .NET container as both the build and runtime environment. Offical .NET Docker images are hosted at https://hub.docker.com/r/microsoft/dotnet. Instructions on how to install Docker can be found from here: Mac , Windows, Linux.
##Application
I am building a solution to solve Poker hands problem. First, Lets get started by adding a project directory.
mkdir poker_hands
cd poker_hands
Then create a new project with the CLI tool
docker run --rm -v "$PWD":/src -w /src microsoft/dotnet:0.0.1-alpha dotnet new
The dotnet new
command adds 3 new files into the working directory
NuGet.Config
Program.cs
project.json
NuGet.Config contains sources that NuGet packages can be loaded from. Program.cs contains application entry point which is a static Main method. Project.json is the project configuration file. Lets take a close look at it. (Note I have made changes to the generated one)
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"NETStandard.Library": "1.0.0-rc2-23811"
"xunit": "2.1.0"
"dotnet-test-xunit": "1.0.0-dev-128011-22"
},
"frameworks": {
"netstandardapp1.5": {
"imports": "dnxcore50"
}
}
}
emitEntryPoint
is set to true, which tells .NET runtime to invoke Main method as entry point when the application runs. For class libraries, this setting is not needed.
In dependencies section, there is NETStandard.Library. This is a reference NuGet Package that references other packages such as System.Console, System.Collections. Unlike .NET framewokr, .NET Core is pay-to-play. To use Console, Collections, Linq and other features in code, corresponding packages must be installed as dependencies. The frameworks section lists all the Frameworks this application supports. Since I am targeting .NET Core only, just netstandardapp1.5 is included. The imports section maps old dnxcore50 to this new moniker. It is also possible to add “net46” to frameworks section. That will enable the application to support .NET framework 4.6. However, doing so will make this application lose its ability to run on a Linux runtime.
To make this application a self-contained docker image, we need a Dockfile
FROM microsoft/dotnet:0.0.1-alpha
RUN mkdir /src
WORKDIR /src
ADD . /src
CMD sh run.sh
run.sh is a helper script that calls restore and build before run
dotnet restore
dotnet build
dotnet run
Run the application
docker build -t problem54 .
docker run -rm -v $(pwd):/src --rm problem54
If everything goes well, you are going to see “Hello World” printed out in the terminal. Not a very exciting application so far.
Unit testing
My first attempt was to use NUnit. However, NUnit console (and the underlying NUnit Engine) do not support running unit tests against .NET core yet. There is a work around according to this answer to my question on Stack Overflow. I gave it a try and it did work. Then I switched to XUnit which comes with a runner supports .NET Core. To use XUnit, add xunit
and dotnet-test-xunit
into dependencies section:
"dependencies": {
"xunit": "2.1.0"
"dotnet-test-xunit": "1.0.0-dev-128011-22",
"NETStandard.Library": "1.5.0-rc2-23931"
}
and add this line to the project.json
"testRunner": "xunit"
Now add a test file and first test.
using Xunit;
using Poker.models;
namespace Poker.tests
{
public class Hand_tests {
[Fact]
public void Hight_card()
{
var result = Game.Judge("8C TS KC 9H 4S 7D 2S 5D 3S AC");
Assert.True(result == 0);
}
}
}
And update the run.sh to
dotnet restore
dotnet build
dotnet test
Run tests:
docker run -rm -v $(pwd):/src --rm problem54
Following the green-red-refactory process, add tests and implementation until all scenarios are covered. Then we get a solution. The final code can be found here.
Summary
In this post I have shown how we can develop and run an application based on .NET Core in a Docker container. Although be in the very early stages, the .NET Command Line Interface tool seems to be as easy to use as NPM or bundler.