How to Create a Custom Windows 10 Docker Image from Hyper-V for Legacy Applications


4 views

When dockerizing legacy Windows applications, we often hit a critical limitation: Microsoft's official Docker images only provide Windows Server Core or Nano Server variants. Many enterprise applications, especially those dependent on specific Windows 10 features or UI components, simply won't run properly on Server editions.

Before beginning, ensure you have:

  • Windows 10 Pro/Enterprise (version 2004 or later) with Hyper-V enabled
  • Docker Desktop for Windows installed
  • Windows Assessment and Deployment Kit (ADK) for DISM tools
  • At least 50GB free disk space

Here's the complete workflow I've successfully used in production environments:

1. Prepare the Hyper-V Base VM

# Create a Generation 2 VM with UEFI
New-VM -Name "Win10DockerBase" -Generation 2 -MemoryStartupBytes 4GB -NewVHDPath "C:\VMs\Win10Base.vhdx" -NewVHDSizeBytes 60GB

# Configure necessary settings
Set-VMProcessor -VMName "Win10DockerBase" -Count 2
Enable-VMIntegrationService -VMName "Win10DockerBase" -Name "Guest Service Interface"

2. Install and Configure Windows 10

Mount a Windows 10 ISO and install with these customizations:

  • Enable Containers feature during setup
  • Disable pagefile and hibernation
  • Install only required Windows components

3. Convert VHDX to WIM Format

# Mount the VHDX
Mount-WindowsImage -Path "C:\mount" -ImagePath "C:\VMs\Win10Base.vhdx" -Index 1

# Export to WIM format
Export-WindowsImage -SourceImagePath "C:\mount\Windows\System32\config\SYSTEM" -SourceIndex 1 -DestinationImagePath "C:\output\win10base.wim"

# Clean up
Dismount-WindowsImage -Path "C:\mount" -Discard

Create a Dockerfile that references your custom WIM:

# dockerfile.win10
FROM mcr.microsoft.com/windows/servercore:ltsc2019 as base

# Copy and apply the custom WIM
COPY win10base.wim /windows/temp/
RUN dism /online /apply-image /imagefile:C:\windows\temp\win10base.wim /index:1 /applydir:C:\

# Final configuration
RUN powershell -Command \
    Enable-WindowsOptionalFeature -Online -FeatureName Containers -All -NoRestart; \
    Remove-Item -Path C:\windows\temp\win10base.wim -Force

To reduce image size (critical for Windows containers):

  • Run disk cleanup: dism /online /cleanup-image /startcomponentcleanup /resetbase
  • Remove unnecessary language packs
  • Compress the WIM using LZX: export-windowsimage -compressiontype lzx

When running containers from this image:

  • Always use process isolation mode: --isolation=process
  • Microsoft licensing still applies - ensure proper CALs
  • Consider using Docker's buildx for multi-stage builds

When dealing with legacy Windows applications that specifically require Windows 10 (not Server Core or Nano Server), the standard Microsoft container images won't suffice. The critical path involves creating a custom Windows 10 image that Docker can consume.

Before starting, ensure you have:

  • Windows 10 Pro/Enterprise with Hyper-V enabled
  • Docker Desktop installed (Windows container mode)
  • Windows Assessment and Deployment Kit (ADK)
  • At least 50GB free disk space

Here's the refined workflow based on your initial approach:

1. Create the Hyper-V VM

Use PowerShell to create a generation 2 VM:

New-VM -Name Win10ContainerBase -Generation 2 -MemoryStartupBytes 4GB
New-VHD -Path "C:\VMs\Win10Base.vhdx" -SizeBytes 50GB -Dynamic
Add-VMHardDiskDrive -VMName Win10ContainerBase -Path "C:\VMs\Win10Base.vhdx"

2. Prepare the Windows 10 Installation

After installing Windows 10 (build 1909 or later recommended):

# Enable container features
Enable-WindowsOptionalFeature -Online -FeatureName Containers -All -NoRestart
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All -NoRestart

3. Convert VHDX to WIM

Use DISM to capture the image:

dism /capture-image /imagefile:Win10Container.wim /capturedir:D:\ /name:"Windows10_Container_Base"

Where D: is the mounted VHDX volume

4. Create Dockerfile

Now create a Dockerfile that references your custom image:

# syntax=docker/dockerfile:1.3
FROM mcr.microsoft.com/windows:10.0.19042.928
COPY --from=localimage Win10Container.wim /Windows/System32/
RUN dism /online /apply-image /imagefile:C:\Windows\System32\Win10Container.wim /index:1

To reduce image size (crucial for Windows containers):

# Cleanup commands to run inside VM before capture
dism /online /cleanup-image /startcomponentcleanup
dism /online /cleanup-image /spsuperseded
del /q/f/s %windir%\logs\*

For CI/CD pipelines, consider exporting the container:

docker export container_name -o win10container.tar
docker import win10container.tar company/win10-legacy-app:latest

License activation: Windows 10 containers require proper licensing. Use KMS or volume activation.

Base layer mismatch: Ensure your host Docker version matches the Windows build version in your image.

Size limitations: Windows containers have a 20GB layer limit. Monitor your image size during build.

When running your container, specify the isolation mode:

docker run -it --isolation=hyperv company/win10-legacy-app

For process isolation (better performance but requires matching host/container versions):

docker run -it --isolation=process company/win10-legacy-app