Running Docker on Windows Server
Microsofts most modern server OS has some technical advantages over it’s predecessor, and together with Docker makes for a very versatile platform to develop large apps, and of course add-ons for Business Central On-Premise. If you’re looking to quickly get a BC on Docker environment up and running, read on!
Step 1: What to get?
- A computer with sufficient resources. Read this blog if you need more information on hardware.
- You might want a hypervisor (VMWare ESXi or Microsoft Hyper-V Server), but it is not necessary. The installation of a hypervisor is skipped in this tutorial, but the hypervisor is referenced here and there.
- Windows Server 2019 Standard (or Datacenter, but not Essentials).
Step 2: Let’s get some software!
Of course, some of you can open MSDN and download Windows Server right there, but not everyone has a subscription, and Microsoft’s server licenses aren’t cheap.
However, if you go to Microsoft’s EvalCenter, you can download an ISO for Windows Server 2019 which can be used for 180 days: More than enough to take a good look at Docker Enterprise.
Once you’re confident you want to keep going you don’t even have to reinstall; you can convert your evaluation to a licensed and activated Windows using the dism tool and your license key.
Make sure you get the Standard or Datacenter Edition.
There’s also a version called Windows Server 2019 Essentials, which I think is similar to the Small Business Server of the past. This version is missing a feature that’s essential for Docker to work: The Containers feature.
Step 3: Install Windows
Duh. Not much to do here, just make sure all updates are installed.
Once you run the Windows installer, it will ask you if you want a GUI or not; keep in mind the GUI will use some memory. Personally, I still think it can be convenient, although PowerShell is just as powerful.
Also good to know: You can find ready to go Windows Server 2019 environments on Azure. Might save you some time!
Step 4: Setting up Docker
In order to run Docker, we need aforementioned Containers-feature on our Windows installation. There’s a separate command to install this, but Docker-guru Tobias Fenster tipped me that installing Docker already does this for you (thanks!).
So let’s install Docker! You can do this through the GUI, or you can run the following PowerShell commands (remember to run PowerShell as Administrator!):
Install-Module -Name DockerMsftProvider -Repository PSGallery -Force Install-Package -Name docker -ProviderName DockerMsftProvider
These commands also let Windows know where to find the Docker repository, and install the product. After this, reboot the server.
Step 5: Preparing Networking
After your server is up again, it might be a good idea to think about what networking you’d like to use. If you use a laptop to access your server, that laptop is probably connected through WiFi and receiving an IP-address through DHCP.
Is your server on the same physical network (not on Azure, but physically in your office)? Then you might want to consider letting your Docker containers also grab an IP-address through DHCP. This will make them available immediately once they’re up and running.
The way Docker sets up containers as standard, they will only be available internally (as seen from the machine on which Docker runs). Inconvenient – we don’t want to do our development work on the Windows Server, but on our daily workstations.
Creating the network
Docker contains various networking drivers for different purposes. For our dev-machine, the “transparent” driver is most important. We can create a transparent network with name “MyNetwork” from PowerShell:
docker network create -d transparent MyNetwork
All is prepared now… unless you couldn’t wait, skipped a few steps, and already created a container, of course 😉 You can still connect these containers to any new network. Since I have a lack of patience, let’s restart the container too:
docker network connect MyNetwork MyContainer docker stop MyContainer docker start MyContainer
Yes, for some reason I do this manually, in two commands. There is also a “restart”-command, but somehow I feel less in control when I use this, because I didn’t see the stopped container.
Anyway, let’s check if everything is up again:
docker ps -a
You should now have a DHCP address on this container. But if you don’t…
Setting a virtual network to Promiscuous Mode on VMWare allows this network to see all traffic passing through the switch. On a machine that’s merely being used for testing/development purposes, it will make your life a lot easier getting DHCP to your VMs.
This should be considered a security hazard: Don’t do this unless only you and your trustees have administrator permissions on your VMs.
If you use Microsoft Hyper-V Server, this contains a similar feature: It’s called MAC Address Spoofing. There’s some more information on enabling it here.
Step 6: Install NAVContainerHelper
Not necessary, but it’s so practical – trust me, you’ll want NAVContainerHelper. Installing can be done from PowerShell, and is very easy:
Yes, that’s all. Just wait, and it will be installed. You can find more information on this tool here.
Step 7: Creating a container with NAVContainerHelper
Since we’re far past TL;DR point, let’s just start with the one and only (okay, almost) command you need. It sets up your container:
New-NavContainer -accept_eula -containerName "freddy" -auth NavUserPassword -imageName "mcr.microsoft.com/businesscentral/onprem
" -updateHosts -additionalParameters @("--network=MyNetwork")
The system will now ask you for a username and password: These are meant to be able to login to your NAV environment later. The sa-password of the SQL-server is also the password you set here. Later, after it finishes, remember to keep the data (about the location of the VSIX etc.) it shows you in the output.
Right, while your PowerShell window is currently working hard, showing you all kinds of GUIDs, pulling FS layers, downloading files and verifying checksums, it might be a good time to analyze what we asked the tool to do here:
New-NavContainer is the command to start a new NAV container.
-accept-eula saves you from typing “y” once. Not very useful, until you start scripting your container builds (I might blog on this later, in which case the link will pop up here)
-containerName “freddy” defines the Docker-name of the container. If your network uses DNS, your container should be reachable through freddy.domain/NAV/ once it’s up and running
-auth NavUserPassword tells the system to setup the container with NavUserPassword authentication. Since I also work with engineers that don’t have a domain account, I prefer this setting, but I think Windows Authentication is also possible.
-imageName “mcr.microsoft.com/businesscentral/onprem” tells Docker exactly what image to get from which repository. There used to be Docker images on the microsoft/ repository also, but as far as I know everything should be moved to mcr.microsoft.com by now. For more information on what’s available, check out this blog by Waldo.
-updateHosts is an option that updates the hosts-file on your system, to allow for “manual DNS”. Necessary if you want to use:
-additionalParameters @(“–network=MyNetwork”) A very useful option of NavContainerHelper: The possibility to pass through standard docker parameters. In this case, it links this container to the network we created in Step 5.
Step 8: Useful Commands
There’s so much more to write, more than enough to fill an extra blog on how to manage a Docker machine, how to automate certain tasks, and how to fix issues… However, to help get you started, I want to limit myself to two more small subjects:
Since I started playing with docker, I have been constantly saving my PowerShell sessions (commands and output). One that comes back a lot is “docker logs”:
docker logs MyContainer
This command will show you all logs that have been produced from the start of your container. Can be very helpful if you have an issue to fix.
If you’re a developer, you’ll want your own license in the container. All you need to add is your containerName and the location of the license file (on the Docker machine).
Step 9: Good luck!
If you have any questions, or if you ran into something I forgot to mention here, feel free to ask/let me know!