← Back to the Blog

Docker and Windows Server Containers: A First Look

By Tim Butler
Docker and Windows Server Containers: A First Look


With the release of Technical Preview 3 (TP3) for Windows Server 2016, Microsoft for the first time have enabled native Containers under the Windows platform. Integrated with this is the Docker support for Windows Server, meaning you can run Docker containers in a Windows environment.

To be perfectly clear, this isn’t the first time containers have been provided under Windows. Odin (a hosting software company) have been providing Windows containers through their own system now for over 10 years. This is no mean feat when you consider they weren’t ever supplied with any source code from Microsoft.

Secondly, Windows containers (even with Docker) are designed to run Windows applications only. All of your existing Linux based Docker containers won’t run under Windows, despite the commonality. I can see this being a common tripping point for those getting started.

There’s also two types of Windows Container technologies too, one based on Hyper-V and the other which runs directly on Windows Server 2016 (known as Windows Server Containers). The latter is what has been provided in this release, so it's what we’ll be testing here.

Getting started with Windows 2016

Windows 2016 Server TP3

The whole installation process is quite simple, select the type of install, select a drive and let it go. In my instance, this was all up and running within 5 minutes and one of the easiest Windows installations I've ever encountered. Certainly, this is a promising start.

Windows 2016 - Start Menu returns..

This was my first use of Windows 2016 and if you’re familiar with Windows 10 and Windows Server 2012, this (at least visually) appears as a middle hybrid ground. In fact, there’s a lot which has been fixed since 2012 R2. The tile navigation was (and still is) a terrible idea for a server, especially when remotely managing them. As the above screenshot shows, Microsoft have returned to the proper start menu driven system which is far more familiar and intuitive. 

Installing Containers

Once you have a base Windows 2016 TP3 installation, you can now install the Windows Server Container components, Docker and a base container image to work from. Microsoft have a guide to step you through the process, which is quite simple. While it’s only 3 steps, the last one needs to download the base image for the containers (over 3GB), so it will take a while to complete.

NOTE: Make sure you follow the official guide above for installing the containers. Without it, none of the containers will work as expected.

Let’s have a look at the PowerShell script to see what it’s actually doing. While one liner installs are nice from a time-saving perspective, you need to inspect them thoroughly to see what they're actually doing. Especially if it was a production server, you should never blindly install any script or package you haven’t checked or don’t understand.

The first step is the creation of a virtual switch for networking the containers. It does this by allocating the range via DHCP and using NAT to access the host / outside world. Next, the container components are installed (Install-Feature -FeatureName Containers) and it then installs a “zdp.cab” if it’s available. This was quite vague and the file didn't actually exist on my system anyway. A Google search doesn’t find many relevant results, the closest I can see is a “Zero Day Package“ which simply suggests the file is a rollup of updates.

The installer then downloads the “ContainerBaseImage.wim” to the local C:. This will take a while, as the base image is still over 3GB. An interesting comment in the PowerShell script is that Microsoft disable the progress bar when downloading as it reduces performance. Curiosity got the better of me and I tested the download (using wget) while showing the progress bar. This took 70% of two cores to display, so they weren’t joking about a performance hit!  Once the .wim file has been downloaded, this is then installs the base container image (using the “Install-ContainerOsImage” command).

Next, Docker is downloaded and installed. This is then setup as a service with the aid of NSSM, the “Non-Sucking Service Manager”. Finally, the base image is tagged in Docker so that it’s ready for use.

Windows Server Containers: A new beginning

At Conetix, we’ve been using the Odin Containers for Windows for over 10 years, so the concept of containers isn't new. There’s a few key differences here however, and certainly this is set to change as the product evolves. The first caveat is that the base image (the .wim file) must match the current host version and patch level exactly. If you patch your server, you need to re-download and install the new container image. I hope that this is a temporary issue and that Microsoft will have some method of automatically updating patch levels before the final release.

Secondly, not everything works smoothly. Expect to re-run some commands and even to destroy / recreate containers in this preview version. All of the commands are via PowerShell, and you’ll need to ensure you’re running PowerShell with Administrator privileges.

Lets start by creating a basic container:

New-Container -Name "WinContainerTest" -ContainerImageName WindowsServerCore -SwitchName "Virtual Switch"

This doesn’t actually start the container, so now we can issue a Start-Container command:

Start-Container WinContainerTest

Windows 2016 - Start Container

PowerShell should display a progress bar as it starts. On my test system, this took about 5 seconds to start so it’s quite quick. Doing something with this container is now slightly more difficult. Despite referencing it by name to create and start, to access it via PowerShell you need to get the ID. Now it could by my lack of PowerShell experience, but the Get-Container either returns some basic output (as shown below), or as an object.

There’s no way (that I can see) of getting the ID directly from the command. So, we need to store the data in a PowerShell object first and then use the ID from the object to enter a PowerShell. Here’s the commands:

$container = Get-Container "WinContainerTest"
Enter-PSSession -ContainerId $container.ContainerId -RunAsAdministrator

We’re now in the Windows Container. To highlight this, I simply ran the “ipconfig command”:

[c2d9f681-aa4]: PS C:\Windows\system32> ipconfig

Windows IP Configuration

Ethernet adapter vEthernet (Virtual Switch-C2D9F681-AA47-4652-B8EC-EED812EF8B25-0):
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::3de8:8a78:5788:8191
   IPv4 Address. . . . . . . . . . . :
   Subnet Mask . . . . . . . . . . . :
   Default Gateway . . . . . . . . . :
[c2d9f681-aa4]: PS C:\Windows\system32> 

While only a very basic test, it's at least shown that Windows 2016 TP3 has a basic, working Container system.

Docker… and Windows

New to Docker? Make sure you’ve read my “What is Docker" article to help get you up to speed. In a nutshell, Docker is application level containers and in the Linux world it’s seen tremendous growth in the last 18 months. Once you’ve started to use Docker, you’ll realise why too. Application deployment becomes easy to manage and very tightly controlled. This will be a great benefit to Windows based applications too.


Lets have a quick look at what images we have:

C:\Users\Administrator> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
windowsservercore   10.0.10514.0        0d53944cb84d        3 weeks ago         9.697 GB
windowsservercore   latest              0d53944cb84d        3 weeks ago         9.697 GB
PS C:\Users\Administrator>

We can see a basic windowsservercore image, so lets fire up a quick interactive (using the -it flags) Docker container:

docker run -it --name dockerdemo windowsservercore powershell.exe

We used the basic core image, than executed PowerShell. While it may not have appeared to do much, if you now run ipconfig you should now see the network details for the container. Here’s the output from my screen:

PS C:\Windows\system32> ipconfig

Windows IP Configuration

Ethernet adapter vEthernet (Virtual Switch-b68c41a9a1a36852173aca061b3e7d70d06c288724c9d04701110b9aa8033d22-0):

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::8817:363c:10d9:b94e
   IPv4 Address. . . . . . . . . . . :
   Subnet Mask . . . . . . . . . . . :
   Default Gateway . . . . . . . . . :
PS C:\Windows\system32>

I ran into a few glitches during my testing, such as not being able to reference a Docker container via the name nor ID. For a first release, there are going to be a few issues like this so it wasn’t a big concern. To clear the issues, I simply restarted the Docker service:

net stop docker 
net start docker

This fixed all of the glitches each time for me, so handy to remember if you’re going to be doing a lot of Docker development under Windows in these early stages.

Let’s just have a look at what other images there are:

docker search microsoft
PS C:\Users\Administrator> docker search microsoft
NAME                    DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
microsoft/iis           Internet Information Services (IIS) instal...   1         [OK]       [OK]
microsoft/dnx-clr       .NET Execution Environment (DNX) installed...   1         [OK]       [OK]
microsoft/ruby          Ruby installed in a Windows Server Contain...   1                    [OK]
microsoft/rubyonrails   Ruby on Rails installed in a Windows Serve...   1                    [OK]
microsoft/python        Python installed in a Windows Server Conta...   1                    [OK]
microsoft/go            Go Programming Language installed in a Win...   1                    [OK]
microsoft/mongodb       MongoDB installed in a Windows Server Cont...   1                    [OK]
microsoft/redis         Redis installed in a Windows Server Contai...   1                    [OK]
microsoft/sqlite        SQLite installed in a Windows Server Conta...   1                    [OK]
PS C:\Users\Administrator>

Great! A few to get started with. As a Python programmer, I was keen to give it a quick go:

docker pull microsoft/python

Now with the image down, we’ll run a quick interactive Python shell, which will destroy itself upon exit:

docker run -it --rm microsoft/python cmd

Unfortunately, it didn’t actually work as expected. I had to specify “cmd” to even get the container to run, and couldn’t find the proper path to have python run yet. Obviously this is still one area they’re working on.


This is very early grounds for Microsoft, so I can’t be too critical about the product. There’s still a long road ahead of them before the containers become a production ready system. At the same time, there’s a lot of promise shown so far. I wasn’t expecting containers to be even previewed this year so it’s a nice little bonus. It has to be re-iterated again, this is a technical preview. Expect bugs and shortfalls, this isn’t a complete system yet. Thankfully, Microsoft have a “Work In Progress” page, which lists all of the current caveats and known issues.

Windows Server 2016 Error

If they do it right, containers provide a great middle ground between installing everything on the one server and having to go completely virtualised. Hybrid models of both hypervised and containerised environments should also be possible, and it’s certainly heavily used in the Linux realm. Providing clean, repeatable application deployments via Docker I’m sure will also make many developers rejoice too.

Reducing the bulk of the underlying server footprint needs to be a strong focus for Microsoft and at least something they at least appear to be working on. Some of the Linux-based OS’s (such as RancherOS) are as light as 20MB to run Docker containers. The base install of Windows 2016 is 11GB and by the time Docker and the container features are installed, it’s already over 20 GB. The base container image is 3GB compressed, so there's still some work to be done here too.

Overall, we're looking forward to the next update and will be closely watching the progress of the Windows Server containers as they evolve and mature.