Guide to GPU Passthrough in dockurr/windows Container
This guide covers passing a GPU through to a Windows VM running inside the dockurr/windows Docker container (which uses QEMU). Passthrough allows the VM to use your host’s GPU for acceleration, gaming, or compute tasks. It’s technical but assumes basic Docker/QEMU knowledge. We’ll focus on Intel iGPU, NVIDIA, and AMD GPUs.
Key Concepts:
- The container runs QEMU to emulate a VM.
- Passthrough happens in two layers: Host → Container → VM.
- For display output (e.g., HDMI), full passthrough is needed; for transcoding/compute, partial may suffice.
- Risks: Binding a GPU to VFIO-PCI detaches it from the host until reboot. It can’t be used by host apps while bound. Reboot restores it.
- Test in a non-production setup.
Prerequisites (All Users):
- Host with KVM support (check
lsmod | grep kvm). - Install host GPU drivers (e.g., NVIDIA/AMD proprietary).
- Enable IOMMU in BIOS (VT-d for Intel, AMD-Vi for AMD) and kernel (add
intel_iommu=onoramd_iommu=onto GRUB). - Docker installed; for Unraid, use the GUI template.
- Backup your setup.
Base Docker Compose (edit as needed):
services:
windows:
image: dockurr/windows
container_name: windows
environment:
VERSION: "11" # Or 10
RAM_SIZE: "16G"
CPU_CORES: "4"
DISK_SIZE: "128G"
devices:
- /dev/kvm
ports:
- 8006:8006 # Web VNC
- 3389:3389/tcp # RDP
- 3389:3389/udp
volumes:
- ./windows:/storage
restart: unless-stopped
stop_grace_period: 2m
For Normal Users (Docker Compose on Linux Hosts)
Intel iGPU Passthrough (Basic, for Transcoding)
Mainly for video encoding/decoding in the VM. May not accelerate desktop/gaming fully.
- Add to compose:
environment: GPU: "Y" devices: - /dev/dri - Run
docker compose up -d. - In VM (via RDP/VNC): Install Intel drivers. Check Device Manager for “Intel Graphics” device.
- Test: Run video transcoding apps. For gaming/desktop, it may show as “GPU DOD” without DirectX—try advanced QEMU args like
-device virtio-gpuinARGUMENTS.
Advanced Intel (GVT-g Virtual GPU)
Better for sharing iGPU without full detach. Works on Intel HD Graphics (e.g., i3-7100+).
- Add kernel params (edit
/etc/default/grub, runupdate-grub, reboot):i915.enable_gvt=1 kvm.ignore_msrs=1 intel_iommu=igfx_off. - Load modules at boot (add to
/etc/modules):vfio mdev kvmgt vfio_iommu_type1 vfio_virqfd vfio_pci. - Find PCI address:
lspci | grep VGA(e.g., 00:02.0). - Check types:
ls /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types. - Pick type (e.g., i915-GVTg_V5_4), check instances:
cat .../available_instances. - Generate UUID:
uuidgen. - Create vGPU:
echo [UUID] > /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/create. - Add to compose
environment:ARGUMENTS: "-device vfio-pci,sysfsdev=/sys/bus/mdev/devices/[UUID],display=off" - Start container. Install drivers in VM. Reboot host to clean up.
NVIDIA Passthrough
For dedicated use (e.g., RTX 3060). Requires detaching from host driver.
- Install NVIDIA Docker runtime.
- Find PCI IDs:
lspci -nnk | grep -i -A 3 'VGA'(e.g., video: 03:00.0 [10de:2503], audio: 03:00.1 [10de:228e]). - Unbind from NVIDIA (as root):
echo "0000:03:00.0" > /sys/bus/pci/devices/0000:03:00.0/driver/unbindecho "10de 2503" > /sys/bus/pci/drivers/vfio-pci/new_id(orecho "0000:03:00.0" > /sys/bus/pci/drivers/vfio-pci/bind)- Repeat for audio.
- Check: Kernel should show
vfio-pci. - Add to compose:
runtime: nvidia environment: NVIDIA_VISIBLE_DEVICES: all # Or GPU UUID ARGUMENTS: "-device vfio-pci,host=03:00.0,multifunction=on -device vfio-pci,host=03:00.1" devices: - /dev/vfio/[GROUP] # Find group via /sys/kernel/iommu_groups/ - Start container. Install NVIDIA drivers in VM. Check Task Manager for GPU.
AMD Passthrough (e.g., RX 570)
Similar to NVIDIA, but may need PCIe root port for stability.
- Find PCI IDs: Same as NVIDIA (e.g., video: 01:00.0, audio: 01:00.1).
- Unbind from AMD driver (similar to NVIDIA, replace vendor IDs like
1002:xxxx). - Bind to VFIO-PCI.
- Add to compose:
privileged: true environment: ARGUMENTS: "-device pcie-root-port,id=pcieport0,bus=pcie.0,chassis=1 -device vfio-pci,host=01:00.0,bus=pcieport0,addr=00.0,multifunction=on -device vfio-pci,host=01:00.1,bus=pcieport0,addr=00.1 -rtc base=localtime" devices: - /dev/vfio/[GROUP] - Start. Install AMD drivers in VM. Test with benchmarks (e.g., Time Spy).
For Unraid Users (GUI Template)
Unraid simplifies Docker but requires extra params for passthrough. Use the dockurr/windows template from CA.
Intel iGPU
- In template: Add Key
GPUValueY. - Add Device:
/dev/dri→/dev/dri. - Save/start. Same as normal users for advanced GVT-g (run commands in Unraid terminal).
NVIDIA
- Install NVIDIA Driver plugin.
- In template:
- Extra Params:
--runtime=nvidia - Key:
NVIDIA_VISIBLE_DEVICESValue:allor UUID (from Tools > System Devices). - Add Devices:
/dev/vfio/[GROUP](find vialspci -nnk). - Key:
ARGUMENTSValue:-device vfio-pci,host=03:00.0,multifunction=on -device vfio-pci,host=03:00.1(adjust IDs).
- Extra Params:
- Save (won’t start yet).
- Terminal: Unbind/bind to VFIO as in normal NVIDIA section.
- Start container. Install drivers in VM.
AMD
Similar to NVIDIA:
- Extra Params:
--privileged - ARGUMENTS as in normal AMD section.
- Add VFIO devices.
- Unbind/bind in terminal.
Automation Tip: Use User Scripts plugin for unbind/bind on array start.
Troubleshooting
- Code 43 Error: Dump ROM (
cat /sys/bus/pci/devices/0000:03:00.0/rom > gpu.rom), add to ARGUMENTS:-device vfio-pci,...,romfile=gpu.rom. - No Detection: Verify IOMMU groups (devices must be isolated or use ACS override).
- Container Won’t Start: Check logs (
docker logs windows) for VFIO access errors—ensure bound correctly. - Performance: Use RDP for low latency; VNC is basic.
- Revert Binding: Reboot host.
- Virt-Manager/SSH: Not supported natively (no libvirt); use RDP instead.
- Testing: Run DXDiag in VM for DirectX info; benchmarks for perf.
If issues persist, search QEMU docs or the GitHub repo for QEMU args. This setup evolves—check for updates.