Guide to GPU Passthrough in dockurr/windows Container

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=on or amd_iommu=on to 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.

  1. Add to compose:
    environment:
      GPU: "Y"
    devices:
      - /dev/dri
    
  2. Run docker compose up -d.
  3. In VM (via RDP/VNC): Install Intel drivers. Check Device Manager for “Intel Graphics” device.
  4. Test: Run video transcoding apps. For gaming/desktop, it may show as “GPU DOD” without DirectX—try advanced QEMU args like -device virtio-gpu in ARGUMENTS.

Advanced Intel (GVT-g Virtual GPU)

Better for sharing iGPU without full detach. Works on Intel HD Graphics (e.g., i3-7100+).

  1. Add kernel params (edit /etc/default/grub, run update-grub, reboot): i915.enable_gvt=1 kvm.ignore_msrs=1 intel_iommu=igfx_off.
  2. Load modules at boot (add to /etc/modules): vfio mdev kvmgt vfio_iommu_type1 vfio_virqfd vfio_pci.
  3. Find PCI address: lspci | grep VGA (e.g., 00:02.0).
  4. Check types: ls /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types.
  5. Pick type (e.g., i915-GVTg_V5_4), check instances: cat .../available_instances.
  6. Generate UUID: uuidgen.
  7. Create vGPU: echo [UUID] > /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/create.
  8. Add to compose environment:
    ARGUMENTS: "-device vfio-pci,sysfsdev=/sys/bus/mdev/devices/[UUID],display=off"
    
  9. 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.

  1. Install NVIDIA Docker runtime.
  2. Find PCI IDs: lspci -nnk | grep -i -A 3 'VGA' (e.g., video: 03:00.0 [10de:2503], audio: 03:00.1 [10de:228e]).
  3. Unbind from NVIDIA (as root):
    • echo "0000:03:00.0" > /sys/bus/pci/devices/0000:03:00.0/driver/unbind
    • echo "10de 2503" > /sys/bus/pci/drivers/vfio-pci/new_id (or echo "0000:03:00.0" > /sys/bus/pci/drivers/vfio-pci/bind)
    • Repeat for audio.
  4. Check: Kernel should show vfio-pci.
  5. 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/
    
  6. 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.

  1. Find PCI IDs: Same as NVIDIA (e.g., video: 01:00.0, audio: 01:00.1).
  2. Unbind from AMD driver (similar to NVIDIA, replace vendor IDs like 1002:xxxx).
  3. Bind to VFIO-PCI.
  4. 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]
    
  5. 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

  1. In template: Add Key GPU Value Y.
  2. Add Device: /dev/dri/dev/dri.
  3. Save/start. Same as normal users for advanced GVT-g (run commands in Unraid terminal).

NVIDIA

  1. Install NVIDIA Driver plugin.
  2. In template:
    • Extra Params: --runtime=nvidia
    • Key: NVIDIA_VISIBLE_DEVICES Value: all or UUID (from Tools > System Devices).
    • Add Devices: /dev/vfio/[GROUP] (find via lspci -nnk).
    • Key: ARGUMENTS Value: -device vfio-pci,host=03:00.0,multifunction=on -device vfio-pci,host=03:00.1 (adjust IDs).
  3. Save (won’t start yet).
  4. Terminal: Unbind/bind to VFIO as in normal NVIDIA section.
  5. Start container. Install drivers in VM.

AMD

Similar to NVIDIA:

  1. Extra Params: --privileged
  2. ARGUMENTS as in normal AMD section.
  3. Add VFIO devices.
  4. 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.