- 本文记录了我在 Linux 主机上通过
`dockurr/windows`项目成功将宿主机显卡直通到 Windows 虚拟机的全过程。 - 包括环境准备、VFIO 配置、IOMMU 启用、Docker Compose 部署,以及中间踩到的坑。
- 希望这篇文章能帮到正在折腾 GPU 直通的小伙伴。
1. 背景介绍
[dockurr/windows] 是一个在 Docker 中运行 Windows 的项目,底层基于 **QEMU/KVM** 虚拟化。
默认情况下,它使用的是模拟显卡,无法充分发挥 GPU 的计算或图形加速能力。 为了让 Windows 虚拟机直接使用宿主机的物理显卡,我们需要用到 **PCI Passthrough(PCI 直通)** 技术。
核心原理:
**VFIO**(Virtual Function I/O)是 Linux 内核提供的虚拟化 I/O 框架,用于安全地将 PCI 设备分配给虚拟机。
**IOMMU**(Input-Output Memory Management Unit)是硬件功能,允许我们隔离设备的内存访问,保证安全性和稳定性。
**PCI Passthrough** 让虚拟机看到的显卡,就像插在它自己的主板上一样。
2. 确认 VFIO
支持首先,我们需要确认内核已经编译了 VFIO 模块。
bash grep VFIO /boot/config-$(uname -r) 如下内容,说明支持 VFIO:
CONFIG_VFIO=m
CONFIG_VFIO_PCI=m
CONFIG_VFIO_IOMMU_TYPE1=m
其中:
- m 表示编译成模块,需要手动加载
- y 表示编译进内核,无需单独加载
加载 VFIO 模块:
sudo modprobe vfio-pci
加载成功后,你会看到 /sys/bus/pci/drivers/vfio-pci/ 目录出现。
3. 启用 IOMMU
显卡直通需要开启 IOMMU,否则无法隔离 PCI 设备。
编辑 GRUB:
sudo nano /etc/default/grub
找到:
GRUB_CMDLINE_LINUX="..."
追加:
intel_iommu=on iommu=pt
如果是 AMD 平台,改成:
amd_iommu=on iommu=pt
更新 GRUB 并重启:
sudo update-grub
sudo reboot
重启后验证:
dmesg | grep -i dmar
正常情况下应该看到:
DMAR: IOMMU enabled
4. 查找显卡的 PCI 信息
我们需要找到显卡的 Bus ID 和 Vendor/Product ID,用于绑定 VFIO 驱动。
lspci -nn | grep -i nvidia
示例输出:
8a:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP106GL [Quadro P2000] [10de:1c30]
含义:
- 8a:00.0 → PCI 设备地址
- 10de:1c30 → Vendor ID(10de = NVIDIA),Device ID(1c30 = P2000)
5. 将显卡绑定到 VFIO-PCI
首先解绑原驱动(如 nouveau 或 nvidia):
echo "0000:8a:00.0" | sudo tee /sys/bus/pci/devices/0000:8a:00.0/driver/unbind
绑定到 VFIO:
echo "10de 1c30" | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id
echo "0000:8a:00.0" | sudo tee /sys/bus/pci/drivers/vfio-pci/bind
验证:
lspci -nnk -s 8a:00.0
应看到:
Kernel driver in use: vfio-pci
6. 确认 IOMMU Group
每个 PCI 设备都属于一个 IOMMU group,我们需要知道显卡的 group ID。
find /dev/vfio
你会看到:
/dev/vfio/vfio
/dev/vfio/8
其中 8 就是显卡所在的 IOMMU group 号。
7. 配置 Docker Compose
dockurr/windows 支持通过 GPU_ACCELERATION 环境变量启用 GPU 直通。 我们需要在 Compose 文件中配置 /dev/vfio/vfio 和 /dev/vfio/ 设备映射。
version: "3.9"
services:
windows:
image: dockurr/windows
environment:
VERSION: "win11"
RAM: "8G"
CPU_CORES: "4"
DISK_SIZE: "64G"
GPU_ACCELERATION: "Y"
devices:
- /dev/vfio/vfio
- /dev/vfio/8 # 显卡所在的 IOMMU group
cap_add:
- NET_ADMIN
- SYS_ADMIN
privileged: true
ports:
- "8006:8006"
- "3389:3389"
说明:
- GPU_ACCELERATION=Y → 启用 GPU 直通支持(官方参数)
- /dev/vfio/vfio → VFIO 主控制设备
- /dev/vfio/8 → 显卡所在的 IOMMU group
8. 启动 Windows 并安装驱动
启动容器后,通过 VNC 或 RDP 登录 Windows 虚拟机,安装显卡驱动(NVIDIA 官网下载)。 安装成功后,设备管理器 中会显示真实的物理显卡,而不是虚拟显卡。
9. 踩坑总结
- VFIO 模块没加载 → /sys/bus/pci/drivers/vfio-pci/ 不存在
- GRUB 参数漏写 → 必须有 intel_iommu=on iommu=pt
- 原驱动占用显卡 → 必须解绑原驱动再绑定 VFIO
- devices 映射缺失 → /dev/vfio/vfio + /dev/vfio/ 缺一不可
- GPU_ACCELERATION 未开启 → 容器不会传递 PCI 设备
- PCI 地址格式错误 → 必须用 0000:bus:slot.func 完整格式
10. 总结
通过以上步骤,我们成功将宿主机显卡直通给了 dockurr/windows 容器内的 Windows 虚拟机。 这种方式的优势:
- 性能接近原生,适合游戏、图形渲染、CUDA 计算
- 不需要额外购买显卡直通专用硬件
- 可以灵活结合 Docker 的部署方式
缺点:
- 对硬件(主板、CPU、BIOS)有一定要求
- 配置过程复杂,新手容易踩坑
发表回复