在 dockurr/windows 项目中实现 GPU 直通

·

  • 本文记录了我在 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. 踩坑总结

  1. VFIO 模块没加载 → /sys/bus/pci/drivers/vfio-pci/ 不存在
  2. GRUB 参数漏写 → 必须有 intel_iommu=on iommu=pt
  3. 原驱动占用显卡 → 必须解绑原驱动再绑定 VFIO
  4. devices 映射缺失 → /dev/vfio/vfio + /dev/vfio/ 缺一不可
  5. GPU_ACCELERATION 未开启 → 容器不会传递 PCI 设备
  6. PCI 地址格式错误 → 必须用 0000:bus:slot.func 完整格式

10. 总结

通过以上步骤,我们成功将宿主机显卡直通给了 dockurr/windows 容器内的 Windows 虚拟机。 这种方式的优势:

  • 性能接近原生,适合游戏、图形渲染、CUDA 计算
  • 不需要额外购买显卡直通专用硬件
  • 可以灵活结合 Docker 的部署方式

缺点:

  • 对硬件(主板、CPU、BIOS)有一定要求
  • 配置过程复杂,新手容易踩坑

Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注