把Windows装进Docker容器里
把Windows装进Docker容器里
本文将详细介绍如何在Docker容器中运行Windows操作系统,包括环境准备、基础使用、加速使用以及一些高级使用技巧。
环境准备
想要使用这个方案,我们需要准备以下三个条件:
- 安装了Docker的操作系统(推荐使用Ubuntu)
- Windows操作系统的安装光盘(支持从WinXP到Win11的版本)
- 开源项目dockur/windows的Docker镜像
安装Ubuntu操作系统和Docker
这套方案采用了KVM加速,因此推荐使用Linux环境。如果你还没有Linux环境,可以参考《在笔记本上搭建高性价比的Linux学习环境:基础篇》的方法进行安装。对于已有Linux环境的用户,可以按照以下步骤安装Docker:
sudo apt install docker.io
完成Docker安装后,需要检查系统是否支持KVM。首先安装cpu-checker
:
sudo apt install cpu-checker -y
然后执行kvm-ok
命令,如果顺利的话,将看到类似下面的日志输出:
# sudo kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used
获取Windows操作系统光盘
虽然开源项目dockur/windows会自动从dl.bobpony.com、archive.org以及微软官网下载合适的英文版系统镜像,但手动下载Windows光盘可以加快系统的安装速度。你可以从微软官网下载所需版本的Windows系统镜像。
获取Windows in Docker容器镜像
获取在Docker中运行Windows的容器镜像有以下两种方式:
直接从Docker Hub拉取镜像:
docker pull dockurr/windows
本地构建镜像:
git clone https://github.com/dockur/windows.git cd windows docker build -t dockurr/windows .
这个镜像主要依赖了几项技术:
- KVM虚拟化
- QEMU模拟器
- Docker容器技术
准备工作完成后,我们就可以开始使用这个有趣的技术方案了。
基础使用
我们先聊聊最简单的使用方案,启动一个“无状态”的临时Windows操作系统,容器会自动下载所需的镜像:
version: "3"
services:
windows:
image: dockurr/windows
container_name: windows
devices:
- /dev/kvm
cap_add:
- NET_ADMIN
ports:
- 8006:8006
stop_grace_period: 2m
将上面的配置保存为docker-compose.yml
,然后使用docker compose up
或docker compose -d
启动服务。
由于没有指定本地的镜像,所以如果你的网络环境访问微软CDN不够快的话,启动过程需要等待一些时间。
当一切就绪后,我们可以使用两种方式来访问这个运行在Docker中的Windows:
- 使用浏览器访问容器所在主机的
IP地址:8006
。 - 使用支持RDP远程访问功能的软件,服务器地址填写
IP地址
,端口填写3389
,用户名填写docker
,密码保持空白。
加速使用Windows容器
如果你的网络环境不是那么好,或者你不想每次启动容器都要等待很久,可以使用下面的方法:
让部署使用加速,主要和两个细节有关:是否进行了容器内容的持久化,是否提供了高性能的安装镜像下载方式。
比如,我们在上面的准备工作中,预先下载好Windows的安装镜像,然后将文件重命名为win11x64.iso
,接着将文件放置在目录的./iso
子目录中。那么,借助Nginx,可以让整个安装部署过程变的飞快:
version: "3"
services:
windows:
image: dockurr/windows
container_name: windows
devices:
- /dev/kvm
cap_add:
- NET_ADMIN
ports:
- 8006:8006
stop_grace_period: 2m
environment:
VERSION: "http://winiso/win11x64.iso"
MANUAL: "N"
volumes:
- ./win:/storage
depends_on:
- winiso
winiso:
image: nginx:alpine
container_name: winiso
volumes:
- ./iso:/usr/share/nginx/html
在上面的配置中,我们增加了一个用来将本地的Windows安装文件转换为dockurr/windows
快速可安装的在线地址的容器。
将配置文件保存为docker-compose.yml
,然后使用docker compose up
或者docker compose up -d
启动配置,我们将看到类似下面的日志:
windows | .
windows | .
winiso | 172.20.2.3 - - [11/Mar/2024:03:54:47 +0000] "GET /win11x64.iso HTTP/1.1" 200 6813366272 "-" "Wget/1.21.4" "-"
windows | . 99% 1.59G 0s
windows |
windows | 6651904K .
windows |
windows | 100% 1.95G
windows | =3.7s
windows |
windows |
windows | ❯ Extracting downloaded ISO image...
windows | ❯ Detecting Windows version from ISO image...
windows | ❯ Detected: Windows 11
windows | ❯ Adding XML file for automatic installation...
windows | ❯ Building Windows 11 image...
windows | ❯ Creating a 64G growable disk image in raw format...
windows | ❯ Booting Windows using QEMU emulator version 8.2.1 ...
下载镜像的速度马上从几MB、几十MB增加到了接近每秒2GB,不到4s就能完成镜像的下载和处理。由于在配置中增加了volumes
卷的持久化(- ./win:/storage
),所以我们可以放心的停止或者重新启动容器,而不必担心每次都要重新初始化“一台”新的Windows Docker容器。
使用技巧
更换Windows版本(不提前准备镜像)
如果你的网络环境非常棒,不需要提前下载安装镜像,或者直接使用云主机进行项目部署,那么可以考虑直接调整配置文件中的内容为合适的数值:
environment:
VERSION: "win11"
支持我们调整使用的值包含:win11
、win10
、ltsc10
、win81
、win7
、vista
、winxp
、2022
、2019
、2016
、2012
、2008
。
调整Windows容器资源配置
默认情况下,这个Windows容器会使用vCPU x2、4GB内存、64G的磁盘空间,来满足Win11的最低安装需求。我们可以根据自己的实际需求,来动态的调整容器的硬件资源限制:
environment:
RAM_SIZE: "8G"
CPU_CORES: "4"
DISK_SIZE: "256G"
比如,在上面的配置中,我们调整CPU核心数到4,内存到8GB,磁盘到256GB。
为容器分配独立的IP地址
默认情况下,Docker会共享宿主机的IP,如果我们想要让容器拥有独立的IP地址,需要先创建一个macvlan
网络:
docker network create -d macvlan \
--subnet=192.168.0.0/24 \
--gateway=192.168.0.1 \
--ip-range=192.168.0.100/28 \
-o parent=eth0 vlan
创建完网卡后,调整上面使用的容器配置,根据自己的需求指定容器IP即可:
services:
windows:
container_name: windows
..<snip>..
networks:
vlan:
ipv4_address: 192.168.0.100
networks:
vlan:
external: true
使用一整块磁盘
如果你的主机上有多块磁盘,或者想将某一块磁盘完整的分配给Windows,可以采用下面的方法,其中DEVICE
将作为你的主磁盘:
environment:
DEVICE: "/dev/sda"
DEVICE2: "/dev/sdb"
devices:
- /dev/sda
- /dev/sdb
在Docker中的Windows使用USB设备
我们首先需要使用lsusb
来获取USB设备的VendorID
和ProductID
,然后将这些信息添加到配置中:
environment:
ARGUMENTS: "-device usb-host,vendorid=0x1234,productid=0x1234"
devices:
- /dev/bus/usb