云计算百科
云计算领域专业知识百科平台

在国产服务器上通过 Docker 部署 Windows 虚拟机

博客文章


📝 在国产服务器(麒麟 V10)上通过 Docker 部署 Windows 虚拟机完整指南

背景:在一台基于海光处理器的麒麟 Linux V10 服务器上,通过 Docker + KVM 方式虚拟化运行 Windows 系统。适用于国产信创环境下需要运行 Windows 应用的场景。


一、环境说明

1.1 服务器硬件

项目配置
操作系统 Kylin Linux Advanced Server V10 (Halberd)
CPU 海光 C86-3G 7380 32核 × 2路 = 128核
内存 502GB DDR4
磁盘 838GB(系统盘)+ 额外数据盘
虚拟化 AMD-V 硬件虚拟化支持

1.2 为什么选择 Docker 方案?

直接安装 qemu-kvm 需要从软件仓库下载大量依赖包,但在单机离线环境下(无法联网),yum 源中可能缺少核心组件。Docker 镜像包含了完整的 QEMU/KVM 环境,只需导入一个镜像即可使用,是离线环境下最便捷的方案。

方案对比:
┌──────────────────┬──────────────┬──────────────────┐
│ 方案 │ 难度 │ 适用场景 │
├──────────────────┼──────────────┼──────────────────┤
│ 直接安装 qemu-kvm│ 中等 │ 能联网的环境 │
│ Docker + QEMU │ 简单 ⭐ │ 离线/快速部署 │
│ VMware/vBox │ 简单 │ 桌面环境 │
└──────────────────┴──────────────┴──────────────────┘


二、环境检查(关键步骤)

2.1 检查 CPU 虚拟化支持

# 检查是否支持 SVM(AMD 虚拟化)或 VT-x(Intel 虚拟化)
grep -E 'svm|vmx' /proc/cpuinfo | head -1
# 输出 svm 表示支持 AMD-V

# 统计支持虚拟化的 CPU 核心数
grep -c svm /proc/cpuinfo
# 输出 128 表示所有核心都支持

预期输出:

flags: fpu vme de pse … svm …

2.2 检查 KVM 内核模块

# 检查 KVM 模块是否加载
lsmod | grep kvm

预期输出:

kvm_amd 135168 0
kvm 786432 1 kvm_amd
irqbypass 16384 1 kvm

如果未加载,手动加载:

sudo modprobe kvm
sudo modprobe kvm_amd

2.3 检查 KVM 设备文件

# 检查 /dev/kvm 是否存在
ls -la /dev/kvm

预期输出:

crw-rw—- 1 root kvm 10, 232 9月 22 2025 /dev/kvm

如果不存在:

# 加载模块后通常会自动创建
sudo modprobe kvm_amd

# 如果仍然不存在,手动创建(不推荐)
sudo mknod /dev/kvm c 10 232
sudo chmod 666 /dev/kvm

2.4 检查嵌套虚拟化支持

# 检查是否启用嵌套虚拟化
cat /sys/module/kvm_amd/parameters/nested
# 输出 1 或 Y 表示已启用

如果返回 0 或 N,启用嵌套虚拟化:

# 临时启用
sudo modprobe -r kvm_amd
sudo modprobe kvm_amd nested=1

# 永久启用
echo "options kvm_amd nested=1" | sudo tee /etc/modprobe.d/kvm.conf

# 验证
cat /sys/module/kvm_amd/parameters/nested

2.5 检查 Docker 环境

# 检查 Docker 版本
docker –version
# Docker version 27.2.0, build 3ab4256

# 检查 Docker 服务状态
systemctl status docker

# 检查 Docker 是否可以运行容器
docker ps

# 测试 Docker 功能
docker run –rm hello-world

2.6 一键检查脚本

将以下内容保存为 check-kvm-env.sh:

#!/bin/bash
echo "=========================================="
echo " KVM & Docker 虚拟化环境检查"
echo "=========================================="

echo -e "\\n[1/6] CPU 虚拟化支持"
if grep -q -E 'svm|vmx' /proc/cpuinfo; then
echo " ✅ CPU 支持硬件虚拟化"
echo " 支持核心数: $(grep -c -E 'svm|vmx' /proc/cpuinfo)"
else
echo " ❌ CPU 不支持硬件虚拟化!"
fi

echo -e "\\n[2/6] KVM 内核模块"
if lsmod | grep -q kvm; then
echo " ✅ KVM 模块已加载"
lsmod | grep kvm | sed 's/^/ /'
else
echo " ❌ KVM 模块未加载!"
echo " 请执行: sudo modprobe kvm && sudo modprobe kvm_amd"
fi

echo -e "\\n[3/6] KVM 设备文件"
if [ -e /dev/kvm ]; then
echo " ✅ /dev/kvm 存在"
ls -la /dev/kvm | sed 's/^/ /'
else
echo " ❌ /dev/kvm 不存在!"
fi

echo -e "\\n[4/6] 嵌套虚拟化"
if [ -f /sys/module/kvm_amd/parameters/nested ]; then
NESTED=$(cat /sys/module/kvm_amd/parameters/nested)
if [ "$NESTED" = "1" ] || [ "$NESTED" = "Y" ]; then
echo " ✅ 嵌套虚拟化已启用"
else
echo " ⚠️ 嵌套虚拟化未启用"
echo " 请执行: echo 'options kvm_amd nested=1' | sudo tee /etc/modprobe.d/kvm.conf"
fi
elif [ -f /sys/module/kvm_intel/parameters/nested ]; then
NESTED=$(cat /sys/module/kvm_intel/parameters/nested)
echo " ✅ Intel 嵌套虚拟化状态: $NESTED"
else
echo " ⚠️ 无法检测嵌套虚拟化状态"
fi

echo -e "\\n[5/6] Docker 环境"
if command -v docker &> /dev/null; then
echo " ✅ Docker 已安装"
echo " 版本: $(docker –version)"
if docker ps &> /dev/null; then
echo " ✅ Docker 服务运行正常"
echo " 运行中容器: $(docker ps -q | wc -l) 个"
else
echo " ❌ Docker 服务未运行!"
fi
else
echo " ❌ Docker 未安装!"
fi

echo -e "\\n[6/6] 系统资源"
echo " 内存: $(free -h | awk '/Mem:/ {print $2 " 总计, " $7 " 可用"}')"
echo " 磁盘: $(df -h / | awk 'NR==2 {print $2 " 总计, " $4 " 可用"}')"
echo " CPU: $(nproc) 核心"

echo -e "\\n=========================================="
echo " 检查完成"
echo "=========================================="

运行:

chmod +x check-kvm-env.sh
./check-kvm-env.sh

预期输出:

==========================================
KVM & Docker 虚拟化环境检查
==========================================

[1/6] CPU 虚拟化支持
✅ CPU 支持硬件虚拟化
支持核心数: 128

[2/6] KVM 内核模块
✅ KVM 模块已加载
kvm_amd 135168 0
kvm 786432 1 kvm_amd

[3/6] KVM 设备文件
✅ /dev/kvm 存在
crw-rw—- 1 root kvm 10, 232 …

[4/6] 嵌套虚拟化
✅ 嵌套虚拟化已启用

[5/6] Docker 环境
✅ Docker 已安装
版本: Docker version 27.2.0
✅ Docker 服务运行正常
运行中容器: 4 个

[6/6] 系统资源
内存: 502Gi 总计, 442Gi 可用
磁盘: 838G 总计, 592G 可用
CPU: 128 核心

==========================================
检查完成
==========================================


三、部署步骤

3.1 准备工作

创建工作目录

# 创建项目目录
mkdir -p /data/windows-vm
cd /data/windows-vm

# 创建存储目录
mkdir -p storage

# 创建共享目录(Windows 可访问的共享文件夹)
mkdir -p share

准备 Windows ISO(可选)

如果有本地 ISO 文件:

# 方式一:直接复制
cp /path/to/windows.iso /data/windows-vm/windows.iso

# 方式二:通过 U 盘挂载
mount /dev/sdb1 /mnt/usb
cp /mnt/usb/Windows10.iso /data/windows-vm/windows.iso
umount /mnt/usb

如果没有 ISO 文件,dockurr/windows 镜像支持 自动下载(需要联网)。

3.2 创建 Docker Compose 配置文件

cd /data/windows-vm
vi docker-compose.yml

将以下内容粘贴进去:

version: '3.8'

services:
windows:
image: dockurr/windows:latest
container_name: windowsvm
privileged: true
devices:
/dev/kvm
ports:
"8006:8006" # Web 安装界面
"3389:3389" # 远程桌面 RDP
volumes:
./storage:/storage
# 本地 ISO
./windows.iso:/storage/custom.iso
environment:
VERSION: "win10" # win8.1 / win10 / win11 / win2019 / win2022
RAM_SIZE: "8G"
CPU_CORES: "4"
DISK_SIZE: "100G"
USERNAME: "xxx"
PASSWORD: "xxxxxx"
restart: unlessstopped

3.3 离线导入 Docker 镜像

如果服务器无法联网,需要在能联网的机器上提前导出镜像:

# ========== 在联网机器上执行 ==========

# 拉取镜像
docker pull dockurr/windows:latest

# 导出镜像为 tar 文件
docker save dockurr/windows:latest -o dockurr-windows.tar

# 查看文件大小
ls -lh dockurr-windows.tar

然后通过 U 盘或内网传输到目标服务器:

# ========== 在目标服务器上执行 ==========

# 导入镜像
docker load -i /path/to/dockurr-windows.tar

# 验证导入成功
docker images | grep windows

3.4 启动 Windows 虚拟机

cd /data/windows-vm

# 后台启动
docker-compose up -d

# 查看启动日志
docker-compose logs -f

首次启动会经历以下过程:

1. 创建虚拟磁盘(100GB) ~30秒
2. 下载/加载 Windows ISO ~取决于网络或文件
3. 自动安装 Windows ~15-30分钟
4. 配置系统和用户账户 ~自动完成

3.5 访问 Windows

安装完成后,通过以下方式访问:

方式地址说明
Web 界面 http://xx.xx.xx.xx:8006 浏览器直接访问,查看安装进度
远程桌面 xx.xx.xx.xx:3389 使用 Windows 远程桌面客户端连接

远程桌面连接信息:

  • 地址:xx.xx.xx.xx
  • 端口:3389
  • 用户名:xxx
  • 密码:xxxxxxxx

四、常用管理命令

4.1 容器生命周期管理

# 进入项目目录
cd /data/windows-vm

# 启动
docker-compose up -d

# 停止
docker-compose stop

# 重启
docker-compose restart

# 查看状态
docker-compose ps

# 查看日志
docker-compose logs -f

# 删除容器(保留数据)
docker-compose down

# 删除容器和数据(慎用)
docker-compose down -v

4.2 直接使用 docker 命令

# 查看容器状态
docker ps -a | grep windows

# 查看资源占用
docker stats windows-vm

# 进入容器(调试用)
docker exec -it windows-vm bash

# 查看容器日志
docker logs -f windows-vm

# 强制重启
docker restart windows-vm

4.3 数据备份与恢复

# 备份虚拟磁盘
cd /data/windows-vm
cp storage/windows.qcow2 /backup/windows-backup-$(date +%Y%m%d).qcow2

# 恢复虚拟磁盘
cp /backup/windows-backup-20250101.qcow2 storage/windows.qcow2

# 备份整个项目
tar czf windows-vm-backup.tar.gz /data/windows-vm/


五、配置文件详解

5.1 版本选择

环境变量值对应版本推荐场景
win10 Windows 10 LTSC 开发测试、日常使用
win11 Windows 11 需要最新功能
win2019 Windows Server 2019 服务器用途
win2022 Windows Server 2022 最新服务器版本

5.2 资源配置建议

版本最低内存推荐内存CPU磁盘
Windows 10 4G 8G 2-4核 60G
Windows 11 4G 8G 2-4核 64G
Win Server 2019 8G 16G 4-8核 100G
Win Server 2022 8G 16G 4-8核 100G

5.3 完整环境变量列表

environment:
# 基本配置
VERSION: "win10" # Windows 版本
RAM_SIZE: "8G" # 内存大小
CPU_CORES: "4" # CPU 核心数
DISK_SIZE: "100G" # 磁盘大小

# 用户配置
USERNAME: "admin" # 用户名
PASSWORD: "Admin@123" # 密码

# 语言和本地化
LANGUAGE: "zh-CN" # 语言(简体中文)
REGION: "China" # 区域
KEYBOARD: "zh-CN" # 键盘布局

# 网络配置
DHCP: "Y" # 使用 DHCP
# IP: "192.168.1.100" # 静态 IP(可选)
# GATEWAY: "192.168.1.1" # 网关(可选)
# DNS: "8.8.8.8" # DNS(可选)

# 安装选项
SKIP_AUTO: "N" # 是否跳过自动安装
HOME_URL: "https://…" # 首次打开的网页

# 产品密钥(可选)
# KEY: "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"


六、性能优化

6.1 磁盘性能优化

# 在 docker-compose.yml 中添加
volumes:
./storage:/storage
environment:
# 启用 virtio 驱动(更快的磁盘 I/O)
DISK_TYPE: "virtio"

6.2 内存优化

# 在宿主机上启用大页内存
echo 1024 > /proc/sys/vm/nr_hugepages

# 在 docker-compose.yml 中挂载
volumes:
– /dev/hugepages:/dev/hugepages

6.3 网络优化

# 使用 macvlan 网络模式(虚拟机获得独立 IP)
networks:
default:
driver: macvlan
driver_opts:
parent: p6p1
ipam:
config:
subnet: xx.xxx.xxx.xx/24
gateway: xx.xx.xx.xx


七、常见问题

Q1:启动时报错 Could not access KVM kernel module

# 检查 KVM 模块
lsmod | grep kvm

# 重新加载
sudo modprobe kvm
sudo modprobe kvm_amd

# 检查权限
ls -la /dev/kvm
sudo chmod 666 /dev/kvm

Q2:启动时报错 Permission denied

# 确保使用 –privileged 模式
# 确保 Docker 用户在 kvm 组
sudo usermod -aG kvm root
sudo usermod -aG docker root

Q3:远程桌面无法连接

# 检查容器是否运行
docker ps | grep windows

# 检查端口是否开放
netstat -tlnp | grep 3389

# 检查防火墙
sudo firewall-cmd –list-ports
sudo firewall-cmd –add-port=3389/tcp –permanent
sudo firewall-cmd –reload

Q4:安装速度很慢

# 查看资源占用
docker stats windows-vm

# 增加分配的资源
# 编辑 docker-compose.yml
# RAM_SIZE: "16G"
# CPU_CORES: "8"

Q5:Docker 镜像导入失败

# 检查 Docker 版本是否兼容
docker version

# 检查磁盘空间
df -h

# 尝试重新导入
docker rmi dockur/windows:latest
docker load -i dockur-windows.tar

Q6:USB 设备直通

Q6.1 应用场景

需要在 Windows 虚拟机中使用宿主机的 USB 设备,如:

  • USB 硬盘 / U 盘
  • USB 加密狗
  • USB 打印机
  • USB 扫描仪
  • 其他 USB 外设
Q6.2 获取 USB 设备信息

# 插入 USB 设备后,执行以下命令查看
lsusb

输出示例:

Bus 002 Device 003: ID 0951:1666 Kingston Technology DataTraveler 100 G3/G4/SE9 G2
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 046d:c52b Logitech, Inc. Unifying Receiver
^^^^ ^^^^
vendorid productid

记录关键信息:

设备vendoridproductid
Kingston U盘 0x0951 0x1666
Logitech 键鼠 0x046d 0xc52b
Q6.3 配置 Docker Compose

version: '3.8'

services:
windows:
image: dockurr/windows:latest
container_name: windowsvm
privileged: true
devices:
/dev/kvm
/dev/bus/usb # USB 总线设备
ports:
"8006:8006"
"3389:3389"
volumes:
./storage:/storage
./windows.iso:/storage/custom.iso
environment:
VERSION: "win10"
RAM_SIZE: "8G"
CPU_CORES: "4"
DISK_SIZE: "100G"
USERNAME: "admin"
PASSWORD: "Admin@123"
ARGUMENTS: "-device usb-host,vendorid=0x0951,productid=0x1666" # USB 设备直通
restart: unlessstopped

关键配置说明:

配置项说明
devices: /dev/bus/usb 映射 USB 总线设备到容器
ARGUMENTS: "-device usb-host,vendorid=xxx,productid=xxx" 指定要直通的 USB 设备
Q6.4 多个 USB 设备直通

environment:
ARGUMENTS: "-device usb-host,vendorid=0x0951,productid=0x1666 -device usb-host,vendorid=0x046d,productid=0xc52b"

Q6.5 使用步骤

# 第一步:Windows 安装完成后,再插入 USB 设备!
# ⚠️ 这一步非常重要,否则会导致磁盘顺序混乱,安装失败

# 第二步:插入 USB 设备,获取 vendorid 和 productid
lsusb

# 第三步:修改 docker-compose.yml 中的 ARGUMENTS
# 将 vendorid 和 productid 替换为你设备的实际值

# 第四步:重建容器
docker-compose down
docker-compose up -d

# 第五步:等待 Windows 启动,U 盘会自动出现在"此电脑"中

Q6.6 ⚠️ 重要注意事项

┌─────────────────────────────────────────────────────────────────┐
│ ⚠️ USB 磁盘驱动器(U盘、移动硬盘)重要提醒 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 必须等 Windows 安装完成后再插入 USB 设备! │
│ │
│ 原因: │
│ 如果在安装过程中插入 USB 磁盘,QEMU 会将 USB 磁盘识别为 │
│ 第一块磁盘,导致 Windows 安装程序将系统装到 U 盘上, │
│ 造成安装失败。 │
│ │
│ 正确流程: │
│ 1. docker-compose up -d │
│ 2. 等待 Windows 安装完成 │
│ 3. 进入 Windows 桌面 │
│ 4. 在宿主机插入 U 盘 │
│ 5. 执行 docker-compose down && docker-compose up -d │
│ │
└─────────────────────────────────────────────────────────────────┘

Q6.7 验证 USB 设备

进入 Windows 后:

1. 打开"此电脑",查看是否出现 U 盘盘符
2. 打开"设备管理器",展开"通用串行总线控制器"
3. 确认 USB 设备已正确识别

Q7:多台虚拟机各挂载一个同型号 USB 设备
Q7.1 问题场景

实际生产中,经常遇到以下情况:

  • 多把同品牌同型号的 UKey(如银行U盾、税务UKey、数字证书锁)
  • 每把 UKey 需要分配给不同的虚拟机独立使用
  • vendorid 和 productid 完全相同,无法通过这两个参数区分
  • 部分设备 iSerial 为空,也无法通过序列号区分

实际设备信息:

Bus 001 Device 005: ID xxx:xxx xxxxxx USB Key ← UKey-1
Bus 001 Device 006: ID xxx:xxx xxxxxx USB Key ← UKey-2
Bus 001 Device 007: ID xxx:xxx xxxxxx USB Key ← UKey-3

# 三个设备的序列号全部为空
lsusb -v -d xxx:xxx2>/dev/null | grep iSerial
# iSerial 0
# iSerial 0
# iSerial 0

Q7.2 解决思路

虽然 vendorid + productid + serial 都无法区分设备,但 QEMU 的 usb-host 参数还支持 hostbus + hostaddr,即通过 USB 总线编号和设备地址来精确定位到某个具体的物理设备。

参数说明示例值
hostbus USB 总线编号(lsusb 输出中的 Bus) 1
hostaddr USB 设备地址(lsusb 输出中的 Device) 5

lsusb 输出:
Bus 001 Device 007: ID xxx:xxx xxxxxxxUSB Key
^^^ ^^^^
hostbus=1 hostaddr=7

Q7.3 VM-1 配置

# docker-compose.yaml
services:
environment:
ARGUMENTS: "-device usb-host,hostbus=1,hostaddr=5"

Q7.4 VM-2 配置

# docker-compose.yaml
services:
environment:
ARGUMENTS: "-device usb-host,hostbus=1,hostaddr=6"

Q7.5 VM-3 配置

# docker-compose.yaml
services:
environment:
ARGUMENTS: "-device usb-host,hostbus=1,hostaddr=7"
restart: unlessstopped


八、目录结构总结

/data/windows-vm/
├── docker-compose.yml # Docker Compose 配置文件
├── storage/ # 虚拟磁盘存储(自动创建)
│ ├── windows.qcow2 # 虚拟磁盘文件
│ ├── custom.iso # ISO 文件(如果有)
│ └── …
└── share/ # 共享文件夹(可选)
└── …


九、总结

步骤命令说明
1. 检查环境 ./check-kvm-env.sh 确认虚拟化支持
2. 创建目录 mkdir -p /data/windows-vm 创建项目目录
3. 编写配置 vi docker-compose.yml 配置文件
4. 导入镜像 docker load -i xxx.tar 离线导入镜像
5. 启动服务 docker-compose up -d 启动 Windows
6. 访问系统 浏览器访问 :8006 Web 管理界面
7. 远程桌面 RDP 连接 :3389 使用 Windows

参考资料:

  • dockur/windows GitHub
  • KVM 官方文档
  • Docker Compose 文档
赞(0)
未经允许不得转载:网硕互联帮助中心 » 在国产服务器上通过 Docker 部署 Windows 虚拟机
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!