Deploying a .NET Application with Docker

Containers are a relatively new phenomenon for Windows. Although containers evolved for 20 years in the Linux ecosystem, they really took off a few years ago with the arrival of Docker. Now, sysadmins and other tech pros can use containers in the context of Windows Server 2016, Windows 10 Professional, and Windows 10 Enterprise.

So what is a container? In simplest terms, it is a lightweight, resource-controlled runtime environment, running on a host or virtual machine, that features everything a developer or sysadmin would need to run code or use tools (i.e., application, database server, web server, configuration files, and so on). The container is isolated away from the rest of the system, which means that tech pros can do whatever they want “inside” it without worrying about the impact on larger infrastructure.

Why Do We Need Containers?

If you’ve ever put an application into production, you might have found out the hard way that it’s a tedious and often painstaking process, with lots of things that can go wrong. Files must be in the right place, config files must be edited, servers set up, and so on.

Any experienced developer has likely encountered a perplexing issue with production: a program will run on one PC, and not another. Maybe the latter isn’t configured right, for example. Such problems aren’t uncommon.

A container eliminates many of these issues. If the container can run on one host, it can be moved to a similar host and run there. That’s quite a remarkable thing, especially when you consider that a container can include an operating system. (For a deeper dive into how Docker works, check out this Dice piece.)

And Docker?

Docker is a way to package images (meaning your application and all of its dependencies). Docker on Windows requires Hyper-V, Microsoft’s built-in virtualization technology (which is why you need Windows 10 Professional or Enterprise and build 14393 or higher).

After installing it, you should see a new item in the system tray that looks like a whale. Right-click on that; in the pop-up menu, you should see “Switch to Windows containers.” It is set to Linux containers by default, but you can switch anytime; for the .NET stuff, we have to use Windows containers.

Run an elevated command prompt. I have a shortcut on the Start menu; right-clicking it lets you run it as Administrator. On the command line, type docker –version to check the install:

D:\devstuff\c#\dotnetapp-4.7>docker --version
Docker version 18.03.1-ce, build 9ee9f40


What’s the Difference?

You can only use Windows containers on Windows Server 2016 or Windows 10 Professional/Enterprise, while Linux containers can be used anywhere. For the purposes of this article, we’ll be using Windows containers.

The next decision is whether to use Nano Server or WindowsServerCore. Nano Server is a cut-down, headless version of Windows Server. It can’t run 32-bit software, nor does it support console login, so we’ll be using WindowsServerCore, which you can install in Docker with this command:

docker pull microsoft/windowsservercore


The download is 5.2 GB. It’s grab-a-coffee time.

E:\>docker pull microsoft/windowsservercore
Using default tag: latest
latest: Pulling from microsoft/windowsservercore
3889bb8d808b: Pull complete
8e9da9bbe3af: Pull complete
Digest: sha256:c06b4bfaf634215ea194e6005450740f3a230b27c510cf8facab1e9c678f3a99
Status: Downloaded newer image for microsoft/windowsservercore:latest


The command docker images now shows which images you have installed in your local repository:

C:\Users\David>docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
microsoft/windowsservercore   latest              9dbf7f740334        3 weeks ago         10.7GB
microsoft/nanoserver          latest              a6688cd24441        3 weeks ago         1.13GB

An Application to Run

For your first application, I suggest you download the .NET framework samples on this page and pick one.

Trying to build one from scratch didn’t go well for me, so I used the samples. I chose the dotnetapp-4.7 sample and had to update my Visual Studio community to build against NET 4.7. You do this by running the Visual Studio installer (on the main menu), then clicking “modify.” If it says “update,” then there’s an update available. Once you click “update,” you’ll get a form with tabs; choose the Individual components and tick the ones you want.

Creating an Image

The file has all the instructions (they are a bit terse). Get to the command line, switch to the folder with the .sln file for the project, and run the build. That folder should also have a Dockerfile:

FROM microsoft/dotnet-framework:4.7
COPY bin/Release/net47 .
ENTRYPOINT ["dotnetapp-4.7.exe"]


Next, we have to build the Dockerfile; this command does that.

docker build -t dotnet47-app .


Now we have the container; we just need to run it with this command:

docker run dotnet47-app


It takes a few seconds to load and run, and outputs a text image in the command prompt window. That longer load time is because the dotnet47-app is a whopping 12.8 GB (but it does include the whole .NET 4.7 framework!).


I’ve just shown a small part of the container “iceberg.” To go further, you should immerse yourself in the Docker ecosystem. Good luck! While containers are a hard concept to grasp in the abstract, they have lots of practical applications.