最初出现在我的博客.

我碰巧在我目前的工作场所Process Street中,我必须修复我们的iOS 应用程序中的一个错误。但是......我想在 Linux 机器上做这个,而不是在 MacBook 上。在这种情况下该怎么办?让我们在虚拟机中运行 macOS!

目录

1.先决条件

*CPU 虚拟化

*RAM,磁盘空间

*码头工人

2.安装Docker-OSX

*开始吧!

*安装操作系统

3.自定义安装

*提取磁盘映像

*添加 RAM 和 CPU

*从主机共享文件夹

*写入共享文件夹

*联网,访问端口

*设置主机网络

*使用 VNC 客户端

4.结论

先决条件

CPU虚拟化

您的 CPU 应支持 Intel VT 或 AMD-V 等虚拟化。在您的 BIOS/UEFI 中启用它,然后再继续。 (例如,在我的 Ryzen 系统上,这是一个必须在 BIOS 中启用的“AMD SVM”设置。)

然后安装内核虚拟化管理器 (KVM) 和 QEMU。对于 Fedora Linux,请参阅此处的文档。很简单:

# sudo dnf install @virtualization

进入全屏模式 退出全屏模式

然后启动libvirtdsystemd 服务并检查kvm内核模块是否正在运行。

借助 KVM,x86 虚拟化提供了接近原生的性能,这意味着来自 Mac 虚拟机的 CPU 调用以安全的方式直接路由到您的处理器,而不会受到任何形式的仿真损失。

尽管图形和一般 UI 响应速度会很慢,但使用 KVM,只要你有一些强大的 CPU,比如更新的 Intel i7 或 Ryzen 7,软件就会运行得非常快。

例如,将 KVM 的效率与DOSBox进行比较,因为 DOS 程序使用低级 BIOS 中断和真实 CPU 模式,所以需要完全仿真。这种模拟可能会慢几个数量级,尽管在今天的机器上模拟 DOOM 时这不是问题。 :)

RAM,磁盘空间

如果您想运行 Xcode,请至少安装 16Gb 的 RAM,以便您可以为虚拟机分配大约 8Gb。

您将需要数十 GB 的磁盘空间。一旦您开始安装软件,QEMU“qcow”图像就会疯狂地扩展,直到它们达到 200 Gb 的预设限制。使用几天后,我的图像文件增长到 170 Gb。因此,请准备好具有足够可用空间的 HDD/SSD。

码头工人

由于我们将使用Docker-OSX项目,因此您需要在本地拉取、运行甚至创建 Docker 映像。您可能对podman很幸运,尽管它与您的系统交互的方式与 Docker 不同。 YMMV。要安装 Docker,请遵循安装指南。

安装Docker-OSX

熟悉 Docker-OSX下载页面。它有一个很好的、很长的自述文件!命令可能会更改,因此请参阅自述文件以获取最新版本。

简而言之,Docker-OSX 运行一个 Arch Linux 容器,该容器执行 QEMU 并为您设置预安装的或 vanilla macOS 映像。可疯狂定制:您可以通过单个docker run命令快速开始,但根据您的需要,您可以自定义虚拟机运行方式的多个方面,如屏幕分辨率、共享文件夹、USB 直通、VNC 连接等。

开始吧!

只需运行一个基本图像。选择您的操作系统版本(Catalina、Big Sur、Monterey)。我建议选择仍然受支持的 Big Sur,但不像 Monterey 那样新,它可能存在一些仿真问题。

运行适当的命令:

docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    sickcodes/docker-osx:big-sur

进入全屏模式 退出全屏模式

这是做什么的?它会拉取一个预构建的 Big Sur 映像,将您的 /dev/kvm设备和一个 X11 套接字转发到容器中。它在主机中的 50922 端口公开容器内的 10022 端口,以进行 SSH 访问(可选)。它还设置了一个环境变量,告诉容器使用哪个 X 显示器。

对于管理 Docker 容器,如果您不想处理命令行,我建议使用 Visual Studio 代码](https://code.visualstudio.com/docs/containers/overview)的[Docker 扩展。非常方便!

基本上,当容器运行时,QEMU 虚拟机将继续运行。如果您从 macOS 内部关闭机器,容器将停止。docker run启动一个全新的容器,但您可以稍后通过docker start启动同一个容器。

安装操作系统

启动后,您将看到 macOS 的恢复安装程序:

Mac VM 的引导加载程序

您必须按照 README 的“附加启动说明”部分来格式化虚拟磁盘映像并在其上安装 macOS(该映像包含预先安装的 Big Sur 安装介质)。

格式化虚拟磁盘映像

这是非常简单的点击式工作,您很快就会收到自己的 macOS 安装!

享受新安装!

从这里开始,如何自定义图像由您决定。我将在这里展示一些技巧!

自定义您的安装

提取磁盘镜像

我建议做的第一件事是提取 macOS 磁盘映像,以便在您试验 VM 设置时,您将拥有所有工作和设置的持久安装。它只是/var/lib/docker中的一个大文件:

sudo find /var/lib/docker -size +10G | grep mac_hdd_ng.img

进入全屏模式 退出全屏模式

将文件复制到有空间增长的方便位置(2-300Gb!)。从这里开始,您可以使用“裸”容器之一创建您自己的自定义映像,在该容器中,该文件只是作为卷安装:

docker run -it \
    --device /dev/kvm \
    -v "${PWD}/mac_hdd_ng.img:/image" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    sickcodes/docker-osx:naked

进入全屏模式 退出全屏模式

从这里开始,为了方便起见,我建议您创建一个文本文件来存储docker run命令的版本。是时候破解了!

添加 RAM 和 CPU

默认情况下,仅使用 4 个内核和 4 Gb 的 RAM 创建 VM。为什么不使用更多?根据您的系统,添加参数-e RAM=8 -e CPU_STRING=16以使其更快、更快!

从主机共享文件夹

这个非常有用,因为您可能想从主机共享一些文件。不幸的是,这并不简单。因为网络开箱即用,如果只是一些较小的文件,您实际上可能会更好地通过 Dropbox 等云提供商共享文件!

请参阅此处的说明。您基本上将文件夹名称作为docker run参数传递,例如-v "$HOME/mac/shared:/mnt/hostshare",并添加一些额外的 QEMU 参数,将这个文件夹定义为一个名为hostshare的设备。此外,在 VM 内部,每次启动后,您必须挂载这个文件夹:sudo -S mount_9p hostshare

在 Finder 的菜单栏中,单击“前往 - 计算机”以访问此共享文件夹。这种共享文件夹不如原生“qcow”磁盘镜像快;不要将它用于包含数千个文件的文件夹,例如 Git repos,这将是一种缓慢的体验。

写入共享文件夹

您可能会注意到您无法写入共享文件夹。这是因为 Linux 权限系统的工作原理:每个用户都有一个与每个文件相关联的 ID。在确定文件系统权限时,实际上使用的是此 ID 而不是您的用户名。

macOS 也是 POSIX 兼容的操作系统,使用相同的访问模型,但您的 macOS 用户很可能默认具有不同的 ID,因此主机操作系统将拒绝权限。

使任何人都可以写入共享文件夹可能会起作用,但从安全角度来看是很糟糕的。幸运的是,您可以使用一些命令来更改您的 macOS 用户 ID。请参阅此处的指南。不是超级复杂,但也不是很简单。如果你打算这样做,我建议在你的 VM 中安装任何软件之前这样做,因为每个文件都需要重置它们的用户 ID。

联网,访问端口

Docker 中的网络本身就很困难,此外,我们正在让这个 VM 在 QEMU 中运行。哎哟。除了浏览网页之外,您可能还有不同的用例,这应该是开箱即用的。

将端口从 VM 转发到主机,例如,在 VM 中运行 nginx 或某些服务器后端是一个有效的用例。对于每个被转发的端口,在设置容器时需要一些额外的参数,请参阅此处的 README 部分。

从 VM 访问主机端口,即localhost访问也可以通过使用-pDocker 参数将相应端口转发到容器来实现。 QEMU 将宿主机的localhost(在 Docker 内部!)设置为10.0.2.2,之后,

设置主机网络

如果您不想单独将端口转发到 Docker 容器中,您可以选择使用“主机网络”驱动程序。在这种情况下,您可以通过10.0.2.2访问所有 Linux 机器的端口。从安全角度来看,这也是一个缺点:只有在您知道自己在做什么的情况下才这样做。

使用 VNC 客户端

默认的 QEMU 窗口可以完成这项工作,但通过 VNC 客户端访问您的 VM 要方便得多。它具有以下优点:

  • 关闭模拟器窗口时不必停止 VM

  • 显示主机的鼠标光标以获得更流畅的体验

  • 捕获键盘快捷键,如CMD+C等。

  • 通过键入从主机剪贴板“插入”(即使没有直接剪贴板共享)

  • 改变连接质量等

我建议使用RemminaVNC 客户端,因为它非常先进,但您可以随意使用自己的客户端。有多种方法可以获得支持 VNC 的版本,最简单的可能是在 repo 中构建一个自定义 Dockerfile(如果需要不同的分辨率,请编辑文件):

$ git clone git@github.com:sickcodes/Docker-OSX.git
$ cd Docker-OSX/vnc-version
$ docker build -t docker-osx:nakedvnc -f Dockerfile.nakedvnc .

进入全屏模式 退出全屏模式

记下构建容器时打印的 VNC 密码!每次运行都将是永久的,因此您可以将其保存到您的 VNC 客户端。您可以通过localhost:5999连接到它。不要忘记在 QEMU 菜单栏和 VNC 客户端中设置“抓取输入”和“隐藏菜单栏”。

如果您终止 VNC 连接,您的 macOS 系统将继续运行。整洁的!

这是我的示例 Docker 命令以供参考,运行支持 VNC 的容器(在上面构建),带有共享文件夹、自定义映像和主机网络。

docker run \
    --device /dev/kvm \
    --network host \
    -v "$HOME/mac/mac_hdd_ng.img:/image" \
    -v "$HOME/mac/shared:/mnt/hostshare" \
    -e EXTRA="-virtfs local,path=/mnt/hostshare,mount_tag=hostshare,security_model=passthrough,id=hostshare" \
    -e RAM=8 \
    -e CPU_STRING=16 \
    docker-osx:nakedvnc

进入全屏模式 退出全屏模式

结论

我希望你喜欢阅读这个小指南。尝试这个实验确实展示了我们当前的虚拟化技术是多么先进,并允许您将 macOS 用于合法用例,例如安全虚拟机内的安全研究。

Logo

更多推荐