Nano Server Container Host

When it comes to Containers we are aiming to detach our self from any of unnecessary bells and whistles that come with modern Server based operating systems. With Nano Server we only use what we need. We don’t have a need for anything besides the essentials that allow us to offer our Application/Content to the world.

This is one of the many reasons why Nano server is a tremendous push forward for not only Microsoft but for any DevOps teams who are wanting to take advantage of this rapid, lightweight deployment option.

I’ve been working with Windows Server Core Containers since the release of Windows Server 2016 TP3 and now that TP5 is out it’s a perfect time to move onto Nano Server Containers!

Firstly if you have not downloaded Windows Server 2016 TP5 yet head over to the Microsoft download page and grab yourself a copy – here. Now that we’ve got our ISO downloaded we need to create a Nano Server Container Host. You’ll also notice that there is a Nano Server VHD file that is available for download from the Microsoft download page. If you want to play around with Nano Server out of the context of creating your own Container Host you can simply download that and mount it in Hyper-V and you’re ready to roll.

Once we’ve downloaded the TP5 ISO we can simply mount it to our local machine. Assuming you are running Windows 10 as your Hyper-V host simply mount the ISO and the first step is complete.

Next I’m going to use a simple GUI for creating Nano Server’s which can be cloned from here

After we’ve dot sourced our function in we can simply run New-NanoServer from the ISE/Console to get our GUI to pop up.


The Domain Name field is left blank if we wish to not join any Domain with our Nano Server. We also specify the media path of our TP5 ISO and a base and target path we can use to build and place our newly created .vhdx (Generation 2) file. We’ve also selected the Containers and DSC package to be part of our Container Host.

Once we’ve hit build we end up with our files ready to roll in our target folder location.


Now that we’ve got our image ready we will need to download a few other bits and pieces for Nano Server to be able to be a real container host. Let’s mount our newly created vhdx file by double clicking on it. Once its mounted (mine was F:) we need to download the Docker daemon and Docker CLI and place thhose on our Nano Server. From an Admin PowerShell window you can run the following:

curl -OutFile F:\windows\system32\dockerd.exe
curl -OutFile F:\windows\system32\docker.exe

Once this has downloaded we should have our Docker daemon sitting nicely on our Nano Server like so.


Now, because we cannot interact with Nano Server directly we need to do some groundwork before we create a new VM and turn it on. We need a way to start the Docker daemon when the Nano Server boots. Microsoft have mentioned this in this post over here and of course this is just a temporary measure until they iron out some of the kinks with Docker on Nano Server. For now, lets go along with it.

We can create our .cmd file as so (Your Nano .vhdx may or may not be F:\):

New-Item -ItemType File -Path F:\ProgramData\Docker\runDockerDaemon.cmd -Force

We can open up that .cmd file and paste in the following contents:

@echo off
set certs=%ProgramData%\docker\certs.d

if exist %ProgramData%\docker (goto :run)
mkdir %ProgramData%\docker

if exist %certs%\server-cert.pem (if exist %ProgramData%\docker\tag.txt (goto :secure))

if not exist %systemroot%\system32\dockerd.exe (goto :legacy)

dockerd -H npipe:// 
goto :eof

docker daemon -H npipe:// 
goto :eof

if not exist %systemroot%\system32\dockerd.exe (goto :legacysecure)
dockerd -H npipe:// -H --tlsverify --tlscacert=%certs%\ca.pem --tlscert=%certs%\server-cert.pem --tlskey=%certs%\server-key.pem
goto :eof

docker daemon -H npipe:// -H --tlsverify --tlscacert=%certs%\ca.pem --tlscert=%certs%\server-cert.pem --tlskey=%certs%\server-key.pem


This file will be called by a small bit of PS code that will allow us to interact with the Docker daemon whenever the Nano Server starts up. Go ahead save the below code into a .ps1 file and save it to your Nano Server in the same directory as the .cmd. In this example I called mine Set-DockerStartup.ps1.

$dockerData = "$($env:ProgramData)\docker"
$dockerDaemonScript = "$dockerData\runDockerDaemon.cmd"
$dockerLog = "$dockerData\daemon.log"
$action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/c $dockerDaemonScript > $dockerLog 2>&1" -WorkingDirectory $dockerData
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet -Priority 5
Register-ScheduledTask -TaskName Docker -Action $action -Trigger $trigger -Settings $settings -User SYSTEM -RunLevel Highest | Out-Null
Start-ScheduledTask -TaskName Docker


So now we have our dockerd.exe in System32 and we have our two files like so below:


Alright, Now lets dismount our .vhdx file and attach it to a newly create VM and fire it up.

Dismount-VHD C:\Nano\NContainer.vhdx #We used this location originally

New-VM -Generation 2 -Name NanoContainerHost -MemoryStartupBytes 1GB -SwitchName (Get-VMSwitch).Name -VHDPath C:\Nano\NContainer.vhdx
Start-VM NanoContainerHost

This should boot up in about 1 second and be sitting at a logon screen for you like so:


Now we’ve got our Server up and running we can use PowerShell Direct to make a remote session to our Container Host.

Enter-PSSession -VMName NanoContainerHost -Credential Administrator

And we’re in!


Now we’re in we need to go and execute that bit of PowerShell code we left in C:\ProgramData\docker\Set-DockerStartup.ps1. Once we’ve run that, the Docker daemon should be up and running. You will be able to see a dockerd.exe process running also if you run Get-Process dockerd.

Now for the icing on the cake let’s create our first Nano Server Container!

To simply list all of the available docker commands you can just type in the word ‘docker’ let’s take a look at our images by running ‘docker images’

Hmmm. strange we have none! well let’s go ahead and download one. To do that we need the Package Provider called ContainerImage. We can install that as such.

Install-PackageProvider ContainerImage -Force

Now we have our Package Provider installed on the Nano Server we can use the Find-ContainerImage cmdlet coupled with the Install-ContainerImage to fetch the latest copy of the Nano Server Container image.

Once you’ve installed the ContainerImage for NanoServer you should have it listed when running ‘docker images’

from here you can do (a very basic container):

docker run -it NanoServer cmd

For further information on Nano Containers please check out the Microsoft post here


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s