体验Windows11上安装Docker-OSX系统

6级英语的郑同事安利的开源项目,不然我都不知道还有那么好玩的东西。

因为我的系统是windows11,安装的过程都非常顺利,没有遇到什么障碍。我开启子系统并升级到wsl2后,ubuntu就已经支持了kvm。

还有,这篇文章只记录操作过程,不保证覆盖到全部的情况,在Windows10下不一定适用。

(English version translate by GPT-3.5)

前言

所有操作均为真实操作,并真实产生的结果。所以我只能记录自己所得到的,所操作的,不能确保覆盖到每一个情况,每一个错误。例如子系统是否支持KVM需要自行检查,我是开启子系统后,升到wsl2,子系统直接支持了kvm,同时也支持子系统GPU调用。

所以,如果子系统起来后没有kvm,就不适用了

项目Git地址 https://github.com/sickcodes/Docker-OSX

本机配置

CPU:Intel® Core™ i7-11800H 2.30GHz
系统:Windows11 Pro

其他就不列出来了吧,因为。用不到啊

开启子系统

  1. 打开开始菜单,进入设置
    开始界面

  2. 然后搜索控制面板
    控制面板

  3. 进入控制面板后,选择 程序 - 启用或关闭Windows功能 - 在弹出的窗口中,拉到底部找到并勾选 适用于Linux的windows子系统以及 虚拟机平台
    开启子系统 WSL2

  4. 系统会要求重启,重启一下

启用WSL2

我的wsl2启用得非常顺利,全程不带阻碍的

  1. 打开开始菜单,直接输入 powershell,然后右键以管理员模式打开(非管理员能否操作我没有尝试过)
    打开Windows powerShell

    1
    2
    3
    4
    5
    6
    Windows PowerShell
    版权所有(C) Microsoft Corporation。保留所有权利。

    安装最新的 PowerShell,了解新功能和改进!https://aka.ms/PSWindows

    PS C:\WINDOWS\system32>
  2. 启用WSL 2

    一行命令

    1
    wsl --set-default-version 2

    返回

    1
    2
    3
    PS C:\WINDOWS\system32> wsl --set-default-version 2
    有关与 WSL 2 的主要区别的信息,请访问 https://aka.ms/wsl2
    操作成功完成。
  3. 更新内核

    也是一行命令

    1
    wsl --update

    返回

    1
    2
    3
    4
    5
    6
    PS C:\WINDOWS\system32> wsl --update
    正在检查更新...
    正在下载更新... // 这里我记得他会自动下载约300MB不到的更新
    正在安装更新...
    此更改将在 WSL 下次完全重启时生效。若要强制重启,请运行“wsl --shutdown”。
    内核版本: 5.10.60.1
  4. 关闭WSL 2来生效

    这句话同时也可以用来停止wsl,省点内存。下次使用Ubuntu的时候他会自动重新开启

    1
    wsl --shutdown

下载并安装Ubuntu 20.04

直接去Windows Store商店搜索 Ubuntu 并安装Ubuntu 20.04
安装Ubuntu 20.04

如果出现下图的情况,先关闭科学上网,Windows store在开启代理的情况下我记得是无法访问的

没有网络的情况

Ubuntu 20.04 中的操作

下载完毕后,在开始菜单中找到Ubuntu 20.04并打开

1
2
3
4
Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username:

输入用户名和密码后,会进入子系统,好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Enter new UNIX username: ruter
New password:
Retype new password:
passwd: password updated successfully
Installation successful!
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.10.60.1-microsoft-standard-WSL2 x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage

System information as of Tue Nov 23 21:15:29 CST 2021

System load: 0.17 Processes: 8
Usage of /: 0.5% of 250.98GB Users logged in: 0
Memory usage: 2% IPv4 address for docker0: 172.17.0.1
Swap usage: 0% IPv4 address for eth0: 172.19.72.129

1 update can be applied immediately.
To see these additional updates run: apt list --upgradable


The list of available updates is more than a week old.
To check for new updates run: sudo apt update


This message is shown once a day. To disable it please create the
/home/ruter/.hushlogin file.
ruter@Ruter-DPC:~$

如果开起来出现 0x800701bc 的错误,指的是WSL2内核忘了升级了

决定性的操作,KVM检查

输入

1
root@Ruter-DPC:/home/ruter# ls /dev/kvm

如果没有任何内容,那。。表示子系统不支持KVM,如果支持,它会输出这样的内容

1
2
3
root@Ruter-DPC:/home/ruter# ls /dev/kvm
/dev/kvm
root@Ruter-DPC:/home/ruter#

安装Docker

根据 Install Docker Engine on Ubuntu 的引导,安装Docker,这里就贴出所有的命令了

1
2
3
4
5
6
7
8
9
10
11
12
13
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

启动Docker

1
service docker start

下载并安装 Docker OSX

下载x11-apps,用来显示图形界(Docker-OSX要求的)

1
apt install x11-apps

直接运行下面的命令

1
2
3
4
5
6
7
8
9
10
docker run -it \
--device /dev/kvm \
-p 50922:10022 \
-p 50599:5999 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-e "USERNAME=user" \
-e "PASSWORD=alpine" \
-e EXTRA="-display none -vnc 0.0.0.0:99,password=on" \
sickcodes/docker-osx:latest

也可以挂载系统盘到子系统某个目录下

如果需要挂载其系统盘到子系统某个目录,自行修改如下命令并运行,这样的好处是,运行命令不管怎么换,磁盘都在,就像一台电脑CPU和显卡怎么换,只要主板和硬盘不换,系统就可以不用做太多操作

1
2
3
4
5
6
7
8
9
10
11
12
13
docker run -it \
--device /dev/kvm \
-p 50922:10022 \
-p 50599:5999 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v "/home/dockerMac/image.img":/image.img \
-v "/home/dockerMac/external.img":/exteralDisk.img \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-e "IMAGE_PATH=/image.img" \
-e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom.plist' \
-e EXTRA='-device ide-hd,bus=sata.5,drive=DISK-TWO -drive id=DISK-TWO,if=none,file=/exteralDisk.img,format=qcow2' \
-e EXTRA="-display none -vnc 0.0.0.0:99,password=on" \
sickcodes/docker-osx:latest

命令详解

端口映射

这2个命令表示映射端口,将Docker中的端口映射到子系统的端口,即当在子系统访问 127.0.0.1:50922时,等同于进入Docker中访问127.0.0.1:10022

1
2
-p 50922:10022
-p 50599:5999
挂载

这2个表示将/这里改成你的目录/你的系统磁盘.img的文件挂载到Docker系统中的/image.img下,Docker OSX默认把/image.img是OS的系统盘(可以通过环境变量IMAGE_PATH来修改OS系统盘路径)
而externalDisk.img可以创建第二块数据盘

1
2
-v "/这里改成你的目录/你的系统磁盘.img":/image.img
-v "/这里改成你的目录/你的第二块数据盘.img":/exteralDisk.img

这里的image需要使用 qemu-img进行创建,系统盘建议120GB起步,它不会一口气吃掉120GB

1
2
sudo apt install qemu-utils
qemu-img create -f qcow2 -o size=120G /这里改成你的目录/你的系统磁盘.img
环境变量部分,这里会大部分引用原文的描述
1
2
3
4
5
-e "DISPLAY=${DISPLAY:-:0.0}" \
-e "IMAGE_PATH=/image.img" \
-e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom.plist' \
-e EXTRA='-device ide-hd,bus=sata.5,drive=DISK-TWO -drive id=DISK-TWO,if=none,file=/exteralDisk.img,format=qcow2' \
-e EXTRA="-display none -vnc 0.0.0.0:99,password=on" \
  1. DISPLAY What is ${DISPLAY:-:0.0}?

  2. IMAGE_PATH=/image.img 将Docker容器中环境变量 IMAGE_PATH设置成/image.img,因为Docker-OSX会去使用这个环境变量来设定其Macos系统的磁盘镜像,但是上面又通过了了-v "/这里改成你的目录/你的系统磁盘.img":/image.img/这里改成你的目录/你的系统磁盘.img 挂载到了 /image.img 中,所以此时 /image.img 的文件其实就是 /这里改成你的目录/你的系统磁盘.img

  3. EXTRA='-device ide-hd,bus=sata.5,drive=DISK-TWO -drive id=DISK-TWO,if=none,file=/exteralDisk.img,format=qcow2'
    这里其实是qemu-kvm中设置磁盘的参数了,详见 qemu-kvm相关文章

  4. EXTRA="-display none -vnc 0.0.0.0:99,password=on"
    这里其实是开启了vnc,后面的99表示使用5999端口,详见 Native QEMU VNC example - Docker-OSX Github

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
root@Ruter-DPC:/home/ruter# docker run -it \
> --device /dev/kvm \
> -p 50922:10022 \
> -p 50599:5999 \
> -v /tmp/.X11-unix:/tmp/.X11-unix \
> -v "/home/dockerMac/image.img":/image.img \
> -v "/home/dockerMac/externalDisk.img":/exteralDisk.img \
> -e "DISPLAY=${DISPLAY:-:0.0}" \
> -e "IMAGE_PATH=/image.img" \
> -e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom.plist' \
> -e EXTRA='-device ide-hd,bus=sata.5,drive=DISK-TWO -drive id=DISK-TWO,if=none,file=/exteralDisk.img,format=qcow2' \
> -e EXTRA="-display none -vnc 0.0.0.0:99,password=on" \
> sickcodes/docker-osx:latest
Unable to find image 'sickcodes/docker-osx:latest' locally
latest: Pulling from sickcodes/docker-osx
5f3642192ce7: Downloading [================================================> ] 224.6MB/232.4MB
.....
Digest: sha256:b3f36dc42598d45a9a577ea417528b4b3c844982d488cd2103e0eaa4897e600c
Status: Downloaded newer image for sickcodes/docker-osx:latest
71b97d3496e1994822e583da8ba121a7a08a5adcf27f1ae6dee8993e468f0565
ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519
nohup: appending output to 'nohup.out'
++ id -u
.......
alsa: Reason: No such file or directory
audio: Failed to create voice `adc'
usb_desc_get_descriptor: 2 unknown type 33 (len 10)
usb_desc_get_descriptor: 1 unknown type 33 (len 10)
qemu-system-x86_64: terminating on signal 2

等它不动了,此时按一下回车,会出现 (qemu)

1
2
3
4
5
...
usb_desc_get_descriptor: 1 unknown type 33 (len 10)
qemu-system-x86_64: terminating on signal 2

(qemu)

修改VNC密码

也可以不通过VNC方式,在启动脚本中删除EXTRA=”-display none -vnc 0.0.0.0:99,password=on”,那么它就会弹出一个窗口来显示界面

输入 change vnc password root,因为RealVNC连接时,默认使用Root用户名

注意每一次启动docker,都需要重新输入 change vnc password来重置密码

1
2
3
(qemu) change vnc password root
Password: ****
(qemu)

VNC连接

下载RealVNC(或者其他VNC工具)

首先得知道虚拟机的IP 可以通过 ip addr获取

1
2
3
4
5
6
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:15:5d:a2:ac:d5 brd ff:ff:ff:ff:ff:ff
inet 172.19.68.215/20 brd 172.19.79.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::215:5dff:fea2:acd5/64 scope link
valid_lft forever preferred_lft forever

可以看到IP是 172.19.68.215,打开RealVNC,并输入 172.19.68.215:50599
RealVNC

输入root后,即可打开页面

连接到VNC

连接成功后,没有意外地话,会看到这个

VNC命令界面

等待若干时间后,会出现这个画面

VNC Apple初始化界面

安装系统

安装界面

接下来,就会出现如下的画面
macOS 实用工具

格式化磁盘

先选择 Disk Utility ,并找到一块137GB的磁盘,右上角Erase抹掉,然后关闭Disk Utility

磁盘工具

重装macOS

然后选择 Reinstall macOS ,并选择刚刚格式化过的磁盘

选择刚刚格式化的磁盘

安装中

漫长的等待(约等待 1小时)

大概需要等待 1小时左右,会进入如下的画面,下面会写着 killing all process

第一次安装完成,重启,共2次

此时在Docker中使用 Ctrl + C来停止服务,然后输入 docker ps -a,找到刚刚停止的容器,并输入 docker start 容器ID

1
2
3
4
5
6
7
(qemu) qemu-system-x86_64: terminating on signal 2
root@Ruter-DPC:/home/ruter# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d4e9307c852 sickcodes/docker-osx:latest "/bin/bash -c 'sudo ..." 14 minutes ago Exited (0) 11 seconds ago upbeat_ellis
root@Ruter-DPC:/home/ruter# docker start 9d4e9307c852
9d4e9307c852
root@Ruter-DPC:/home/ruter#

上面的9d4e9307c852就是容器的Id

这时候会以后台运行的方式运行容器,通过 docker attach 容器ID 来连接到容器

1
docker attach 9d4e9307c852

按一下回车,就会出现 (qemu)

1
2
3
root@Ruter-DPC:/home/ruter# docker attach 9d4e9307c852

(qemu)

重新输入 change vnc password root 并输入你的密码

注意:一定要通过 Ctrl + P + Q 的方式来退出,直接Ctrl + C,容器就又会关闭了,Ctrl + P,按住不要放,再按Q

如果希望停止容器 输入 docker stop 9d4e9307c852 即可


继续安装macOS

此时VNC画面会出现,选择第二个 macOS installer

第二次安装,继续安装macOS

继续漫长的等待(大概30分钟)

等待半小时后,就好了

第二次安装完成

然后,又是一堆English,此时 docker restart 9d4e9307c852 来重启下Docker(别忘了设置vnc密码),重启后,进入VNC,选择刚刚格式化的磁盘

选择Macintosh HD启动macOS

经过简单的设置(Apple ID是可以跳过的)

完毕

基本体验感受

试用了一会,发现速度还是可以的,比之前我在Vmware中运行要快得多了,这个其实是在Docker容器中运行KVM虚拟机,然后在KVM虚拟机中运行Macos镜像,但是用来写代码啥的还是不太行。

系统流畅度可以接受的,但是GPU调用不了(我的子系统是可以调用GPU的),不知道有没有其他能调用GPU的方法。我自己有mac,所以。。。这也就折腾折腾把。

附:如果不加VNC那一行

如果在docker run时去掉 -e EXTRA="-display none -vnc 0.0.0.0:99,password=on"这一行,这样,docker在运行后,自动弹出一个 Qemu的窗口,如图(其实上面)。

如果不适用vnc,那么会弹出QEMU的窗口

附:MacOS的系统信息和性能情况

About This Mac

mac系统信息

Disk speed test

Disk speed test磁盘测试

Geekbench 5 跑分

宿主机跑分 X15 R1 - GeekBench Browser

别问我为啥我的 11800H 分数这么低,因为我把睿频关了,关睿频后折腾上面的东西鸦雀无声,开睿频可以跑到近9000,但是电脑会有概率从桌上起飞

宿主机跑分

子系统跑分 Ubuntu 20.04.3 LTS - GeekBench Browser

神奇,子系统分数比宿主机都高

子系统 Ubuntu20.04跑分

Docker OSX 跑分 IMacPro1.1 - GeekBench Browser

Docker-OSX系统跑分