Normal view

There are new articles available, click to refresh the page.
Before yesterdayPRIN BLOG

在 M1 Mac 上运行 macOS 虚拟机

By: prin
26 November 2021 at 18:30

Apple M1 芯片问世一年有余,时至今日,在 M1 Mac 上运行 Windows、Linux 虚拟机的方法都已经比较成熟了。然而 macOS 本身的虚拟化却并非如此:直到 Monterey 发布,于 M1 Mac 上运行 macOS 虚拟机才成为可能。

最近有几个小实验需要在 macOS 虚拟机上跑,本来以为去 Parallels Desktop 上开一个就完事了,搜了一下才发现,其实事情没那么简单……实际配置过程中也是踩了几个坑,所以顺带记录一下。

前提

目前想要在 M1 Mac 上运行 macOS 虚拟机,有以下要求:

  • Host OS 和 Guest OS 都必须是 Monterey
  • 安装镜像必须是 IPSW 格式

为什么 Big Sur 不行?因为在 Virtualization framework 中运行 macOS 虚拟机是 Monterey 才加入的功能

那以前怎么就能虚拟呢?因为 ARM 架构的 M1 Mac 在引导上用的其实是 iOS 那一套,不是传统的 UEFI,所以苹果官方没提供 bootloader 的话自然没戏。黑苹果也是一样的道理,只能说且用且珍惜吧。

至于 .ipsw 文件,这玩意其实就是 iOS 固件的格式……真就大号 iPad 呗!

IPSW 镜像文件可以在这里下载:Apple Silicon M1 Full macOS Restore IPSW Firmware Files Database – Mr. Macintosh

Veertu's Anka

这个是我目前最推荐的一种方法,所以放在第一个说。

Anka 是什么?根据官网的介绍,Anka 是一个专门用来管理 macOS 虚拟机的软件,可以与现有的基于容器的 DevOps 工作流集成,为 iOS 应用的构建与测试提供 CI/CD 自动化支持。再看下其开发者 Veertu,也是做 iOS CI 和 macOS 云这一块的。

并且今年十月发布的 Anka 3.0 (beta) 已经支持在 M1 Mac 上创建 macOS 虚拟机了,正是我们所需要的。

下载 Anka M1 beta 版,安装后打开,就可以直接通过图形界面创建虚拟机了:

anka-m1-beta

或者,你也可以使用命令行创建虚拟机(相关文档在这里):

anka create --ram-size 4G --cpu-count 4 --disk-size 80G \  --app ~/Downloads/UniversalMac_12.0.1_21A559_Restore.ipsw 'macOS 12'

运行虚拟机:

anka start -uv

Anka 默认将虚拟机存储在 ~/Library/Application Support/Veertu/Anka 目录下,可以参考这里修改保存位置,或者干脆做个软链接也行。虚拟机的配置文件也在同目录下的 config.yaml 文件中,有些图形界面不提供的配置项可以在这里修改。

也可以使用命令行修改,比如修改虚拟机的分辨率和 DPI:

anka modify 'macOS 12' display -r 2560x1600 -d 220

另外,Anka 提供的 Guest Tool 会自动打开虚拟机内 macOS 的自动登录、SSH 并且阻止系统休眠(应该都是为了自动化服务的),并且提供了剪贴板共享、anka cp 文件复制,以及可以直接在虚拟机内执行命令的 anka run 等功能。

anka-macos-vm

不过有一个需要顾虑的是 License 的问题,在 beta 期间可以免费使用 Anka 没问题,但不知道正式版发布以后如何。不过原本 Veertu 家面向个人开发者的 Anka Develop 就是免费的,所以或许并不需要担心。

或者,你也可以使用本文最后提到的开源方案,体验也是不错的。

Parallels Desktop

毕竟是 Mac 虚拟机行业名声最响的,其实我第一个想到的也是 PD。

查了一下,macOS 作为 Guest OS 是 PD17 才支持的功能(前略,天国的 PD16 用户),然后 17.1 更新添加了 Parallels Tools 的支持,还提了一嘴「虚拟机默认磁盘大小从 32 GB 增加至 64 GB」。

我最开始还不知道这有什么好拿出来说的,后来才知道原因:你在 PD 中甚至无法调整 Mac 虚拟机的磁盘大小。不仅是磁盘,CPU 核心数、内存大小、网络连接方式都不能改,可配置项为零(至少无法在图形界面中配置),完完全全就是个半成品。

如果你确实想安装,这里是官方教程:Install macOS Monterey 12 virtual machine on a Mac with Apple M1 chips

点「新建虚拟机」以后,安装助手里就有直接下载 macOS 的选项。看起来很友好,然而……

pd-vm-installation-failed

啃哧啃哧下载了半天,最后提示「安装系统时出错」,也不知道为什么。查了下官方 Knowledge Base,貌似也不是个例:Inability to create a macOS Monterey 12 VM on Mac computers with Apple M1 chips

后来我找到了这篇文章:Customizing MacOS guest VMs in Parallels 17 on Apple Silicon,按照其中的介绍,通过命令行创建虚拟机,竟然就可以运行了……

/Applications/Parallels\ Desktop.app/Contents/MacOS/prl_macvm_create \  ~/Downloads/UniversalMac_12.0.1_21A559_Restore.ipsw \  /Volumes/xxx/Parallels/macOS\ 12.macvm \  --disksize 80000000000

我之前用 17.0.1 版本的时候也尝试用 prl_macvm_create 创建虚拟机,但是在进度到 90% 的时候失败了,提示「内部虚拟化错误。安装失败」。升级到 17.1.0 后虽然安装助手还是「安装系统时出错」,但命令行是可以正常创建虚拟机的。

命令行启动虚拟机:

/Applications/Parallels\ Desktop.app/Contents/MacOS/Parallels\ Mac\ VM.app/Contents/MacOS/prl_macvm_app \  --openvm /Volumes/xxx/Parallels/macOS\ 12.macvm

安装完成后,在 PD 控制中心可以导入 .macvm 格式的虚拟机文件,导入以后就可以从图形界面启动了。

pd-macos-vm

作为一个商业虚拟机软件,且不说快照、Suspend,连最基本的 VM 管理功能都欠奉,我也是无话可说了。想知道还有哪些功能是目前还不能用的,可以查看 Known issues and limitations

MacVM

MacVM 是一个开源项目,基于 Virtualization framework(当然啦,大家都是用的这个),提供了简单的图形界面用于配置虚拟机。

因为作者并没有提供编译好的程序,所以需要自己使用 Xcode 从源码编译。

下载源码,用 Xcode 打开 MacVM.xcodeproj,在 Signing & Capabilities 中修改为自己的开发者证书:

macvm-xcode

点击运行,会跳出来一个文件选择框,不用管先叉掉。

然后菜单栏 File -> New,新建虚拟机。输入 CPU 核心数、内存和磁盘大小后点菜单栏 File -> Save 保存,会生成一个 .macosvm 包。之后虚拟机的虚拟磁盘镜像也会保存在这个 bundle 中,所以要留意选择保存的位置。

macvm-new-vm

然后点 Select IPSW and Continue 按钮,选择之前下载的镜像文件,点 Install,等它安装完就好了。(最开始的版本还要自己生成磁盘镜像,然后拷贝到应用容器中,还要用 Apple Configurator 2 手动装系统,相比起来现在已经友好很多了)

安装完成后,窗口会整个儿变黑,此时就可以点右上角的启动按钮启动虚拟机了。

macvm-success

用这种方法优点是开源,有啥不爽的都可以自己改,包括没有提供配置项的地方。缺点就是要自己编译,毕竟不是谁都装了 Xcode 的。

跑起来以后和上面两种基本没差别,因为实际的虚拟机创建、安装和运行都是 Virtualization framwork 实现的,整个项目的代码其实并不多。

GitHub 上还有一些类似的项目,这里也列出来供参考:

最后

以上三种方法,其实底层大家都是一样的,就看在此之上谁做得更完善了。综合来看,目前感觉 Anka 的使用体验是最好的。

关于 M1 Mac 运行 macOS 虚拟机的一些参考链接:

UTM 有一个 dev-monterey 分支,我还没有尝试,不知道以后会不会推出支持 macOS Guest 的版本。

听说还有人使用 OSX-KVMDocker-OSX 跨架构在 M1 上运行了 x86 的 macOS,但是性能很糟糕(simulation 嘛)。

另外,以上的这些虚拟机方案都不支持快照恢复,有点麻烦。不过好在我用来放虚拟机的移动硬盘是 APFS 格式的,支持写时复制 (Copy on write),所以直接把镜像整个儿复制一份就好了,很快,也不会占用多余的存储空间。

在 M1 Mac 上构建 x86 Docker 镜像

By: prin
17 February 2021 at 05:38

今天闲来无事,数了一下服务器上在跑的东西,打算把它们都扔到 Docker 里面去。第一个开刀的就是之前写的 Google Analytics 博客阅读量统计,很简单的一个 Node.js + Express 程序。

写完 Dockerfile 测试好,正准备 push 上去时,我才突然想起来:

我现在用的是 M1 MacBook,丫的默认 build 出来的镜像是 arm64 架构的呀!

好在 M1 Mac 上的 Docker Tech Preview 也支持使用 buildx 构建多架构的镜像,稍微设置一下就可以了。

题外话,M1 MacBook Air 真的很好用,建议早买早享受(

启用实验性功能

Docker 的 buildx 还是实验性功能,需要在 Docker Desktop 设置中开启,具体位于 Preferences > Experimental Features > Enable CLI experimental features

新建 builder 实例

Docker 默认的 builder 不支持同时指定多个架构,所以要新建一个:

docker buildx create --use --name m1_builder

查看并启动 builder 实例:

docker buildx inspect --bootstrap
Name:   m1_builderDriver: docker-containerNodes:Name:      m1_builder0Endpoint:  unix:///var/run/docker.sockStatus:    runningPlatforms: linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/arm/v7, linux/arm/v6

其中 platforms 就是支持的架构,跨平台构建的底层是用 QEMU 实现的。

构建多架构 Docker 镜像

使用 buildx 构建:

docker buildx build \  --platform linux/amd64,linux/arm64  --push -t prinsss/google-analytics-hit-counter .

其中 -t 参数指定远程仓库,--push 表示将构建好的镜像推送到 Docker 仓库。如果不想直接推送,也可以改成 --load,即将构建结果加载到镜像列表中。

--platform 参数就是要构建的目标平台,这里我就选了本机的 arm64 和服务器用的 amd64。最后的 .(构建路径)注意不要忘了加。

构建完 push 上去以后,可以查看远程仓库的 manifest:

docker buildx imagetools inspect prinsss/google-analytics-hit-counter
Name:      docker.io/prinsss/google-analytics-hit-counter:latestMediaType: application/vnd.docker.distribution.manifest.list.v2+jsonDigest:    sha256:a9a8d097abb4fce257ae065365be19accebce7d95df58142d6332270cb3e3478Manifests:  Name:      docker.io/prinsss/google-analytics-hit-counter:latest@sha256:bb7f3a996b66a1038de77db9289215ef01b18e685587e2ec4bb0a6403cc7ce78  MediaType: application/vnd.docker.distribution.manifest.v2+json  Platform:  linux/amd64  Name:      docker.io/prinsss/google-analytics-hit-counter:latest@sha256:94ea08ac45f38860254e5de2bae77dee6288dd7c9404d8da8a3578d6912e68e7  MediaType: application/vnd.docker.distribution.manifest.v2+json  Platform:  linux/arm64

可以看到已经是支持多架构的镜像了。

参考链接

❌
❌