Running NAV docker containers on a local Hyper-V Virtual Machine

There are already a lot of blog posts about running Dynamics NAV on Docker and how to deal with it. Here are some sites you should definitely start with:
This is the best source to get up to date on the current status of NAV on Docker images.
For in-depth tips and tricks how to deal with Docker in general and NAV on Docker in particular.
The official Microsoft repository for Dynamics NAV on Docker resources.

After playing around a lot with the NAV docker containers on Azure VM’s and local Hyper-V machines, I decided that it’s about time to get to a stable environment. Of course I could go with an Azure VM and run everything in there. Which is not the cheapest option and you don’t have access when you’re offline.

Running containers locally on Windows 10 is an option and I have certainly tried that. However, I ran into all kind of network issues and it didn’t work out really well. So I figured that running containers on a local Hyper-V VM would be the best option.

Then you have the choice between running everything inside the VM, including a desktop with Visual Studio Code, or to only run NAV containers inside the VM and connect to it from the desktop of the host machine, my Windows 10 laptop.

The easiest option is to run an Hyper-V VM with Windows Servier 2016 and desktop enabled so you can install VS Code and run it all on the VM However, it leaves me with two desktops: the desktop on my Windows 10 laptop and the one inside the VM. Maybe that is not bad after all, but I like to do everything from just one desktop, where I have access to all my files.

So the VM should just be server, just like any other server on Azure or at one of my customers. I have Visual Studio Code on my local machine and connect from my desktop directly to a NAV server, no matter if that NAV server is inside a container on a local VM, on an Azure VM or maybe directly installed on a server somewhere in the network.

The challenge was how to set this up in such a way that it works independently from the location I’m working. It should work while I’m at home, at a customer, in a hotel, at a conference, during a workshop or when I’m just offline.

The only way to achieve this is to make the VM independent of any network. It should have it’s own network settings. All containers inside the VM should get an ip-address that is in the same network subnet. This blog post is about setting up this scenario.

Here are the steps I followd to set up this scenario:

  1. Create a Hyper-V virtual network switch
  2. Create and configure a Hyper-V VM
  3. Install Docker on the VM
  4. Create a Docker transparent network in the VM
  5. Create and run the Docker container

Tip: In case you are not interested in the networking stuff, but you are looking for setting up a clean Windows Server 2016 with Desktop Experience and Docker, then skip to step 3.

1. Create a Hyper-V virtual network switch

It is a normal setup to attach a Hyper-V VM to the external network of the host. E.g. the same network as the LAN of Wifi of my laptop. As a result, de VM gets its own ip address when it starts. Which means that the ip-address can vary when you work on different locations.

To be able to give the Hyper-V VM a fixed ip address that is accessible by the host, you need to create an internal Hyper-V virtual network switch and establish a NAT network between.

I followed the steps as explained here and here. So in PowerShell on my Windows 10 desktop with Hyper-V installed I executed these lines:

New-VMSwitch -SwitchName "InternalSwitch" -SwitchType Internal
New-NetIPAddress -IPAddress -PrefixLength 24 -InterfaceAlias "vEthernet (InternalSwitch)"
New-NetNat -Name MyInternalnetwork -InternalIPInterfaceAddressPrefix

As a result, I have an internal network, only visible for my laptop, in the ip-range and bound to the new VM switch ‘InternalSwitch’. Only when I come across a network that uses the exactly the same subnet, I might have a problem. That’s something to keep in mind! If you follow these steps, you are free to use the same ip address range or pick another one as long as it is in one of these ranges:

  •  –
  • –
  • –

2. Create and configure a Hyper-V VM

I’m not going to explain how to create a Hyper-V VM with Windows Server 2016 Core installation on it. What is important is to connect that VM to the internal network. So in the settings of my VM (which I named “Deep Thought”) change the Network Adapter to the InternalSwitch that was created with PowerShell.


Then, inside the Hyper-V, change the network settings. Because the internal network does not have a DHCP server nor a DNS server, you need to set a fixed ip address and DNS servers. This is a one-time setting. Without DNS servers, the VM will not have access to the internet.

Connect to the VM using Hyper-V console. At the command prompt type in sconfig.


This will give the Windows Server 2016 server configuration menu.


Choose 8 to open the Network Settings menu. and then choose the index number of the Microsoft Hyper-V Network Adapter.


The 169.254.x.x address is automatically assigned when no DHCP server could be found. Now choose 1 to set the network address to and choose 2 to set the DNS servers to and (the DNS servers of Google).


After this, you should have internet access from the Hyper-V. Test it with a ping command to any site.

The VM network adapter is now configured for one ip address. Because every individual container inside the VM will get its own ip address, there will be multiple ip addresses going through the same VM network adapter. This is only possible when the VM network adapter is configured for MAC address spoofing. To enable this run the following command on your host. The vm name must be the name that is visible in your Hyper-V management console.

Get-VMNetworkAdapter -VMName "<vm name>" | Set-VMNetworkAdapter -MacAddressSpoofing on

3. Install Docker on the VM

This part is independent of all the network stuff and also works when you want to set up a clean Windows Server 2016 with Desktop Experience and run docker containers inside it.

First step is to make sure that the Windows Server is up to date. From the server config menu choose option 6 Download and Install Updates.


When this is ready, start powershell and install the windows feature Containers with the PowerShell command

Install-WindowsFeature containers

Reboot the machine after the installation.


After the reboot log in again and open powershell. Now you must install the PowerShell module for Docker. This will install the docker service. Don’t forget to reboot after the installation.

Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
Install-Package -Name docker -ProviderName DockerMsftProvider
Restart-Computer -Force


A great post of these steps can also be found here.

From now on, you can use docker commands to pull images and run containers. I have posted earlier about this. But I definitely recommend to go with the PowerShell module navcontainerhelper, created by Freddy Kristiansen. Read his blog post about this and follow it on GitHub.

To install the navcontainerhelper, use the PowerShell command

Find-Module navcontainerhelper | Install-Module


Tip: Skip to 5. Create and run a Docker container if you don’t want to use all this network stuff.

4. Create a Docker transparent network in the VM

Docker has several network options. By default, a NAT network is installed. New containers are connected to this NAT network and will not be visible from outside. To access the container from outside the VM, you need to map port numbers on the external network interface of the VM.

To avoid configurations like port 7049 is mapped to navserver1, port 7149 is mapped to navserver2, etc., I decided to install a docker transparent network. With a transparent network, the containers are directly connected to the external network of the VM. By providing an ip address to each container it becomes possible to access them directly from outside the VM by using their ip address. That is easier to work with, also because the ip addresses can be saved in the hosts file so I can even access the containers by name.

To create a docker transparent network we first need to delete the automatically created NAT network and tell docker to not create it anymore. In PowerShell we execute these lines:

Stop-Service Docker
Get-ContainerNetwork -Name nat | Remove-ContainerNetwork -Force


Next step is to tell docker to not create the NAT network anymore. This is a setting in the daemon.json file. In a fresh installation, this file will not exist. So we are safe to run these commands in PowerShell:

'{"bridge":"none"}' | Set-Content C:\ProgramData\docker\config\daemon.json
Start-Service Docker


The Get-ContainerNetwork now shows the only available network, the Hyper-V internal network.

Next step is to create the transparent network. I tried to use the docker network create command, but for some reason the created network did not what I expected. But the PowerShell cmdlet New-ContainerNetwork did the job.

New-ContainerNetwork -Name tlan -SubnetPrefix -GatewayAddress -Mode Transparent -DNSServers,


As you can see, the parameters use the same ip range as the Hyper-V internal network. The gateway is the ip address of the NAT network on the host machine. You may need to restart the docker service after the network has been created (Restart-Service docker).

The name tlan that is specificied in the parameters is important, because we use that name when we create the docker containers.

5. Create and run the Docker container

We are ready to create a NAV docker container. That can be done with the command New-NavContainer or New-CSideDevContainer. These commands were installed with the module navcontainerhelper that we installed earlier. For more info about these commands, use the Get-Help and read this blog post by Freddy.

New-NavContainer -accept_eula -containerName navserver -imageName microsoft/dynamics-nav -alwayspull -additionalParameters @("--network=tlan","--ip")


The parameter additionalParameters contains these parameters:

  • –network=tlan
  • –ip

With these parameters, the docker engine will create a container that is attached to our internal network. As a result, the container can be connected to directly from the Windows 10 desktop, outside the VM. When I add this ip address to the hosts file, I can even reach the container by its name.


Tip: when you were looking to set up a clean Windows Server 2016 with Desktop Experience environment without all the network stuff, then you should just remove additionalParameters from the New-NavContainer command. The server will be available from the VM desktop after creation.

Final result

All these steps lead to this situation:

  • Hyper-V VM with Windows Server 2016 Core
  • Fixed ip address, indepent from my location
  • Containers have their individual ip address and are direct accessible from the Windows 10 desktop, no port mapping needed

This screenshot is from VS Code, sitting on my Windows 10 desktop, connecting directly to the docker container inside the Hyper-V VM (the new developer endpoint is automatically enabled on docker containers, no need to configure it):


The vsix file can be downloaded:


And what’s more, with PowerShell I can directly tap into the VM and even into the container from my desktop. To enable this, you need first to run the PowerShell cmdlet Enable-PSRemoting on the VM.


Now it might happen that you get an error message when you try to do Enter-PSSession. If  that error message read as follows, then there is a simple solution

Enter-PSSession : Connecting to remote server navserver failed with the following error message : The WinRM client cannot process the request. If the authentication scheme is different from Kerberos, or if the client computer is not joined to a domain, then HTTPS transport must be used or the destination machine must be added to the TrustedHosts configuration setting.

The reason for this message is that you are trying to connect to a server that is outside your domain. You could try to set up a connection over HTTPS, but that requires certificates and is more complex. Instead, follow the other suggestion from the message: add the VM to the TrustedHosts configuration setting on your local machine.

How to do that? Start with finding out the current setting of the TrustedHosts. The PowerShell command for that is:

Get-Item WSMan:\localhost\Client\TrustedHosts

In most cases, the value will be empty. Now simply add the name of your VM to the list.  The PowerShell command for that is:

Set-Item WSMan:\localhost\Client\TrustedHosts -value <computername>

PowerShell must be run in Administrative mode for this command!

You can also use the -value * to add all computernames. A detailed explanation of all options can be found here.

Wait, I’m not done yet. What about C/SIDE and exported objects? Well, now that the Hyper-V VM has an ip address, it’s simple to create a network drive mapping to the C: drive of the VM and access all container data.


Every server has its own folder with C/SIDE in it:


Just run it from there and open the database, directly from the desktop! Use sa as your user id and the password that you specified when you created the container.



I hope you enjoyed this and got some inspiration how to set up a local development environment that it totally indepent of your actual network and transparent to your own desktop.

Ok, one final remark. Just 31 seconds to spin up a new NAV container, how about that?


Comment List