If you’re a .NET developer, you’ve probably been wondering how to run your app in a container and take advantage of the isolated and portable nature of containers. This article will give you the full lowdown on Windows Containers, to prepare you to do just that.
First, I want to acknowledge that there is a big difference between Linux and Windows containers. Linux containers have been around for many decades, in one form or another. The Linux operating system naturally lent itself to taking advantage of containers using namespaces and control groups (cgroups). Windows, however, has been slow to adapt, proving a challenge (to say the least) to reduce bloat and properly isolate services. In this article, I’m not going to go too much into what containers are, but provide rather a “state of the union” for Windows containers. If you’d like to learn more about what containers are, you can find information in this course on Linux Academy.
So why do we even need Windows containers? Well, one of the biggest benefits to Windows containers (besides agility, portability, density, and rapid scale) is the ability to use the same toolset throughout your environment(s). If you’re an IT manager, this means you don’t have to continually train your team on multiple technologies. If they know Docker, they can manage Linux and Windows containers simultaneously using the same commands and tools.
There are two types of Windows Containers: Hyper-V containers and Windows Server containers. Hyper-V containers are running containers inside of a Hyper-V VM, in isolation mode. Each running container is isolated inside a Hyper-V VM. To actually keep it to one windows container per Hyper-V VM, they had to make the VM as small as possible, referred to as a “Utility VM”. To create this utility VM, they made a “special” version of windows which is just a smaller version of the Windows OS. This OS contains only the necessary pieces it needs in order to run.
To increase storage efficiencies between the container and host, the VM uses SMB protocol over VM bus. Unlike a traditional VM, the containers running on this “utility VM” share the same file cache, so each copy of a program on each container can use shared memory from the host.
Here’s a command to run a Hyper-V container:
|C:\> docker run –isolation=hyperv mcr.microsoft.com/windows/servercore:ltsc2019 cmd|
Here’s the architecture of a container running with Hyper-V isolation:
Windows Server Containers, on the other hand, run directly on the Windows kernel, running Dockerd. Docker on Windows is a port of Docker (not a fork). It has the same remote API, and the same tools that work on top (Compose, Swarm, etc.). It does NOT run Linux Containers. The contents of a Windows Server container are separated into two major parts: system processes and application processes. Because Windows does not document its syscalls (a lot of its “baked in” to the Windows OS) internally, DLLs call each other by Remote Procedure Calls (RPC) calls (hidden in Win32 APIs).
This makes it impossible to run a single process in isolation (due to all the other user-mode things). Also, it’s hard to package up all those DLLs into a smaller sized image. SMSS (Session Manager Subsystem) is the inner-process behind the scenes which you can see in the task manager on your host when you run a Windows Container.
Here’s a command to run a Windows Server container:
C:\> docker run mcr.microsoft.com/windows/servercore:ltsc2019 cmd
Here’s the architecture of a Windows Server Container running directly on the Windows kernel:
If we were to zoom in on a Windows host running a Windows Server Container, here’s what we’d see:
Which Option Do I Use?
You may have already formulated your opinion about which type of Windows container is better, but how do you choose? Well, in some cases you don’t have a choice. For example, if you are running Docker on your Windows 10 machine, you are forced to use Hyper-V VMs. This is because Windows Server containers and the underlying host share a single kernel, and Windows 10 is a different Windows kernel than Windows Server. Windows also requires the host OS version to match the container OS version. You can read more on Windows Container Version Compatibility in our Container Docs.
If you’re running container workloads on VMs in Azure, you need to make sure you have the right VM SKU. You need a SKU that has nested virtualization in order to run Windows Containers. The following VM SKUs use nested virtualization in Azure:
Windows Container Images
There are a lot of Windows Container images on Dockerhub and other public repositories that I would encourage you to look at here: https://hub.docker.com/_/microsoft-windows-base-os-images. Some of them include certain libraries for running IIS, .NET, or .NET core applications. Fundamentally, they all derive from three base images: Windows Server Core, Nano Server, and Windows Base OS.
In this article, we’ve unpacked the basics of Windows Containers, viewed the architecture around Hyper-V containers and Windows Server containers, deciphered running containers on VMs in Azure, and learned which ones to run for your workloads.
I hope this has given you a better understanding of Windows Containers and how they operate beneath the surface. I also encourage you to play around in our Azure Cloud Sandbox and create an Azure virtual machine (Standard_D2s_v3 SKU and Windows Server 2019) to start creating your own Windows Server Containers.
If you’re ready to try what you’ve learned, you can get up and running in just TWO STEPS:
STEP 1 – Install Docker:
|# open PowerShell and add the Docker module|
Install-Module DockerMsftProvider -Force
# install the Docker package
Install-Package Docker -ProviderName DockerMsftProvider -Force
# reboot Windows Server
STEP 2 – Run a Windows Container
|# run a Windows Server container|
docker run hell-world:nanoserver-1809
# Congratulations! You have successfully run a Windows Container!
Find even more containers courses and test your knowledge with over 350 different containers courses and labs.