How to Set Up Windows Server 2019 Hyper-V Containers
Hyper-V containers on Windows Server 2019 provide hardware-level isolation by running each container in a lightweight virtual machine with a dedicated kernel. Unlike process-isolated Windows containers that share the host OS kernel, Hyper-V containers ensure that a compromised container cannot affect the host or other containers. This makes them ideal for running untrusted workloads, multi-tenant environments, and scenarios where strong security boundaries are required. This guide covers the setup, configuration, and management of Hyper-V containers on Windows Server 2019.
Understanding Hyper-V Container Isolation
Hyper-V containers use the same Docker tooling and image format as process-isolated Windows containers. The difference is at runtime: Hyper-V containers boot a minimal Hyper-V VM (called a Utility VM or UVM) for each container instance. This means each container has its own isolated memory, CPU, and kernel, but still uses the same Windows container image format. The tradeoff compared to process-isolated containers is slightly higher startup time (a few seconds versus milliseconds) and marginally increased resource overhead.
Prerequisites
Hyper-V containers require the Hyper-V role installed on the host, in addition to the Containers feature. Nested virtualization must be enabled if the host is itself a Hyper-V VM. Install both required features:
Install-WindowsFeature Hyper-V -IncludeManagementTools -Restart
After the server restarts, install the Containers feature:
Install-WindowsFeature Containers -Restart
Install Docker Engine:
Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
Install-Package -Name docker -ProviderName DockerMsftProvider -Force
Restart-Computer -Force
Enabling Nested Virtualization (for VM hosts)
If the Windows Server 2019 host is running as a Hyper-V VM, nested virtualization must be enabled from the parent host before Hyper-V containers will work. Run this on the parent Hyper-V host with the VM shut down:
Set-VMProcessor -VMName "ContainerHost2019" -ExposeVirtualizationExtensions $true
Also enable MAC address spoofing on the VM’s network adapter for container networking to function correctly:
Get-VMNetworkAdapter -VMName "ContainerHost2019" | Set-VMNetworkAdapter -MacAddressSpoofing On
Running Hyper-V Isolated Containers
To run a container with Hyper-V isolation, use the –isolation=hyperv flag with docker run. This instructs Docker to use the Hyper-V container runtime instead of the default process isolation:
docker run -it --isolation=hyperv mcr.microsoft.com/windows/servercore:ltsc2019 cmd
Inside the container, verify that isolation is Hyper-V by checking the kernel version (it will match the container image, not the host):
ver
systeminfo | findstr /B /C:"OS Version"
Run a detached Hyper-V container with port mapping and resource limits:
docker run -d `
--isolation=hyperv `
--name hv_webserver `
--cpus 2 `
--memory 4g `
-p 443:443 `
mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
Setting Hyper-V Isolation as the Default
You can configure the Docker daemon to use Hyper-V isolation by default for all containers, eliminating the need to specify the flag on every run command. Edit the Docker daemon configuration:
$daemonConfig = Get-Content "C:ProgramDatadockerconfigdaemon.json" | ConvertFrom-Json
$daemonConfig | Add-Member -Type NoteProperty -Name "exec-opts" -Value @("isolation=hyperv") -Force
$daemonConfig | ConvertTo-Json | Set-Content "C:ProgramDatadockerconfigdaemon.json"
Restart-Service docker
Alternatively, create the daemon.json directly with all required settings:
@"
{
"exec-opts": ["isolation=hyperv"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"storage-driver": "windowsfilter",
"dns": ["10.0.0.1", "8.8.8.8"]
}
"@ | Set-Content "C:ProgramDatadockerconfigdaemon.json"
Restart-Service docker
Cross-Version Compatibility
One of the key advantages of Hyper-V containers is that they allow running container images built for different Windows Server versions on a Windows Server 2019 host. For example, running a Windows Server 2016 image on a 2019 host requires Hyper-V isolation because the host kernel version does not match the image kernel version:
docker run -it --isolation=hyperv mcr.microsoft.com/windows/servercore:ltsc2016 cmd
This works because each Hyper-V container starts its own dedicated kernel that matches the image, providing full compatibility without requiring the host to match the image version.
Managing Hyper-V Container VMs
Each running Hyper-V container appears as a Hyper-V VM to the host. You can view these VMs using the Hyper-V PowerShell module:
Get-VM | Where-Object {$_.Name -like "Container*"} | Select Name, State, CPUUsage, MemoryAssigned
Hyper-V container VMs are automatically created and deleted by Docker. Do not manually delete or modify these VMs, as Docker manages their entire lifecycle.
Networking for Hyper-V Containers
Hyper-V containers support the same Docker network drivers as process-isolated containers. The key difference is that network endpoints are attached to the container’s UVM rather than the host directly. Create a dedicated network for Hyper-V containers:
docker network create `
--driver nat `
--subnet 172.30.0.0/16 `
--gateway 172.30.0.1 `
HyperVNAT
Run a Hyper-V container on this network:
docker run -d `
--isolation=hyperv `
--network HyperVNAT `
--name secure_app `
contoso/myapp:v2
Monitoring Hyper-V Container Resource Usage
Monitor resource usage across all containers including Hyper-V isolated ones:
docker stats --no-stream --format "table {{.Name}}t{{.CPUPerc}}t{{.MemUsage}}t{{.NetIO}}t{{.BlockIO}}"
Check the isolation type of each running container:
docker inspect --format "{{.Name}}: {{.HostConfig.Isolation}}" $(docker ps -q)
Hyper-V containers on Windows Server 2019 provide the best of both worlds: the convenience and tooling of Docker containers combined with the security isolation of full VM virtualization. They are the recommended choice for multi-tenant environments, processing untrusted payloads, and ensuring compliance requirements around workload isolation are met without sacrificing the operational benefits of containerization.