Docker build not working on a Windows Server virtual machine
Building a docker image that uses an older version of Windows Server for its core image on a Hyper-V machine
TL:DR
If you're using a Windows Server OS on a Hyper-V host to build or run a docker image that uses an older Windows Server base image, you need to enable nested virtualization for the virtual machine on your Hyper-V host and use the --isolation=hyperv parameter when running the docker build or run command.
Using an older Windows Server OS base image and then building on a Windows Server 2022 Hyper-V virtual machine
I use a Windows Server 2022 virtual machine as a dev machine, this allows me to use VSCode on any machine and then SSH in to create, run and debug code. The setup works surprisingly well, until recently when I was trying to update a docker image to use the mcr.microsoft.com/windows/servercore:ltsc2019 base image. The reason for needing to update the image was because Azure container instances don't currently support Windows Server 2022 container images.
The first error message (forcing docker to use Hyper-V and not process isolation)
This didn't initially seem like it was going to be a big issue, just a quick single-line change, however, when building the image, I was given the following error...
The container operating system does not match the host operating system.
At first, I thought my docker settings may have changed (meaning docker was using Linux containers) but after checking the docker icon in the system tray this wasn't the case.
After checking my settings, I remembered that containers running on Windows Server behave differently to containers running on Windows 10 and 11. On server editions of Windows, process isolation is used while Windows 10/11 will uses Hyper-V isolation. After reading over Microsoft's documentation on Windows Server host OS compatibility, Windows Server 2022 can only use process isolation for base images using Windows Server 2022 so to use a Windows Server 2019 base image I'll need to use Hyper-V isolation.
You can force docker build and run to use Hyper-V isolation by using the --isolation=hyperv parameter when building or running an image.
The second error message (enabling nested virtualization)
After adding the --isolation=hyperv parameter got a new error message...
The virtual machine could not be started because a required feature is not installed.
This initially is a bit of a strange error as my Windows Server 2022 virtual machine already had Hyper-V installed (but I hadn't tried using it yet). Doing some Googling, I came across a post by the Windows Club which mentioned to 'Enable Nested Virtualization'. This linked me to another article explaining what it was. It turns out that to allow Hyper-V to function within a Hyper-V machine, you need to enable nested virtualization.
Following a link to [a Microsoft article](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/nested-virtualization, to enable nested virtualization you need to stop the virtual machine you want to enable it for (in my case this was my Windows Server 2022 VM) and then run the following command on the Hyper-V host (the machine that actually runs the VM):
Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true
Finally docker build works
After starting up my development machine VM again I ran docker build --isolation=hyperv --no-cache -t my/image:tag . and got another error message...
unexpected EOF
Reviewing things, docker had decided to update when I was running the build command. So, while the update was happening, I edited the dockerfile around the step where it failed (by removing and then adding the new lines) in notepad.
Once docker had finally finished updating, I ran the same docker build command again and finally my docker image was built successfully.