ITADN
sickcodes/Docker-OSX
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

Docker-OSX · 在 Twitter 上关注 @sickcodes

Running Mac OS X in a Docker container

在 Docker 中以接近原生的性能运行 Mac OS X!X11 转发!iMessage 安全研究!iPhone USB 可用!在 Docker 容器中运行 macOS!

使用 Linux 和 Windows 对 macOS 进行安全研究!

Docker-OSX 现已拥有 Discord 服务器和 Telegram!

Discord 在 #docker-osx 频道中活跃,欢迎任何人前来提问、分享想法等。

点击加入 Discord 服务器 https://discord.gg/sickchat

点击加入 Telegram 服务器 https://t.me/sickcodeschat

或者如果是私密的,请通过 Linkedin 联系: https://www.linkedin.com/in/sickcodes

或者通过 https://sick.codes/contact/

作者

本项目由 Sick.Codes 维护。 (Twitter)

更多致谢信息可在此处找到: https://github.com/sickcodes/Docker-OSX/blob/master/CREDITS.md

此外,所有贡献者的完整列表可在此处找到: https://github.com/sickcodes/Docker-OSX/graphs/contributors

特别感谢 @kholia 维护上游项目,Docker-OSX 正是基于该项目构建的: OSX-KVM

还要特别感谢 @thenickdude,他维护着有价值的分支 KVM-OpenCore,该分支由 @Leoyzen 发起!

特别感谢 OpenCore 团队: https://github.com/acidanthera/OpenCorePkg。他们精心维护的引导加载程序为 Docker-OSX 用户提供了许多出色的功能 :)

如果你喜欢这个项目,请考虑在此处或上游进行贡献!

Docker-OSX 快速入门

视频设置教程也可在此处找到: https://www.youtube.com/watch?v=wLezYl77Ll8

Windows 用户: 点击此处查看以下说明

第一次来?试试 初始设置,否则请尝试以下说明以使用 Catalina 或 Big Sur。

有任何问题、想法,或者只是想闲聊?

https://discord.gg/sickchat

发布名称及其版本:

Catalina (10.15) https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest

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

# docker build -t docker-osx .

Big Sur (11) https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest

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

# docker build -t docker-osx .

Monterey (12) https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest


docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e GENERATE_UNIQUE=true \
    -e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom.plist' \
    -e SHORTNAME=monterey \
    sickcodes/docker-osx:latest

# docker build -t docker-osx .

Ventura (13) https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest


docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e GENERATE_UNIQUE=true \
    -e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom.plist' \
    -e SHORTNAME=ventura \
    sickcodes/docker-osx:latest

# docker build -t docker-osx .

Sonoma (14) https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest


docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e GENERATE_UNIQUE=true \
    -e CPU='Haswell-noTSX' \
    -e CPUID_FLAGS='kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on' \
    -e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom-sonoma.plist' \
    -e SHORTNAME=sonoma \
    sickcodes/docker-osx:latest

# docker build -t docker-osx .

红杉 (15) https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest


docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e GENERATE_UNIQUE=true \
    -e CPU='Haswell-noTSX' \
    -e CPUID_FLAGS='kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on' \
    -e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom-sonoma.plist' \
    -e SHORTNAME=sequoia \
    sickcodes/docker-osx:latest

# docker build -t docker-osx .

Tahoe (16) https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest


docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e GENERATE_UNIQUE=true \
    -e CPU='Haswell-noTSX' \
    -e CPUID_FLAGS='kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on' \
    -e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom-sonoma.plist' \
    -e SHORTNAME=tahoe \
    sickcodes/docker-osx:latest

docker build -t docker-osx .

旧系统

High Sierra https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest


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

# docker build -t docker-osx .

Mojave https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest


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

# docker build -t docker-osx .

手动下载镜像并在 Docker 中使用

https://img.shields.io/docker/image-size/sickcodes/docker-osx/naked?label=sickcodes%2Fdocker-osx%3Anaked

这是一种特别好的下载容器的方式,以防 Docker 的 CDN(或您的连接)恰好很慢。

wget https://images2.sick.codes/mac_hdd_ng_auto.img

docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v "${PWD}/mac_hdd_ng_auto.img:/image" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e GENERATE_UNIQUE=true \
    -e MASTER_PLIST_URL=https://raw.githubusercontent.com/sickcodes/Docker-OSX/master/custom/config-nopicker-custom.plist \
    -e SHORTNAME=catalina \
    sickcodes/docker-osx:naked

共享目录、共享文件、共享文件夹、挂载文件夹

最简单且最安全的方式是 sshfs

# on Linux/Windows
mkdir ~/mnt/osx
sshfs user@localhost: -p 50922 ~/mnt/osx
# wait a few seconds, and ~/mnt/osx will have full rootfs mounted over ssh, and in userspace
# automated: sshpass -p <password> sshfs user@localhost:/ -p 50922 ~/mnt/osx

(VFIO) iPhone USB 直通 (VFIO)

如果您使用的是笔记本电脑,请参阅下一节 usbfluxd 部分。

如果您使用的是台式机,您可以使用 @Silfalion 的说明:https://github.com/Silfalion/Iphone_docker_osx_passthrough

(USBFLUXD) iPhone USB -> 网络式直通 OSX-KVM Docker-OSX

usbfluxd 的视频设置教程也可在此处获取:https://www.youtube.com/watch?v=kTk5fGjK_PM

iPhone USB passthrough on macOS virtual machine Linux & Windows

此方法在笔记本电脑、PC 等任何设备上均可正常工作!

感谢 @nikias 通过 https://github.com/corellium 提供的 usbfluxd

这是在 Linux 内部完成的。

在 Linux 上打开 3 个终端

在 Linux 上通过 USB 连接您的设备,允许您使用 https://github.com/corellium/usbfluxdusbmuxd 暴露在端口 5000 上,供同一网络上的另一台系统使用。

确保已安装 usbmuxdsocatusbfluxd

sudo pacman -S libusbmuxd usbmuxd avahi socat

在 AUR 上可用:https://aur.archlinux.org/packages/usbfluxd/

yay usbfluxd

插入你的 iPhone 或 iPad。

Terminal 1

sudo systemctl start usbmuxd
sudo avahi-daemon

Terminal 2:

# on host
sudo systemctl restart usbmuxd
sudo socat tcp-listen:5000,fork unix-connect:/var/run/usbmuxd

Terminal 3:

sudo usbfluxd -f -n

连接到运行 usbfluxd 的主机

这是在 macOS 内部完成的。

安装 homebrew。

172.17.0.1 通常是 Docker 网桥 IP,即你的 PC,但你可以使用 ip addr 中的任何 IP...

macOS 终端:

# on the guest
brew install make automake autoconf libtool pkg-config gcc libimobiledevice usbmuxd

git clone https://github.com/corellium/usbfluxd.git
cd usbfluxd

./autogen.sh
make
sudo make install

接受 USB over TCP 连接,并显示为本地:

(你可能需要将 172.17.0.1 更改为主机的 IP 地址。例如,检查 ip addr

# on the guest
sudo launchctl start usbmuxd
export PATH=/usr/local/sbin:${PATH}
sudo usbfluxd -f -r 172.17.0.1:5000

关闭 Xcode 等应用程序并重新打开,你的设备应该会显示出来!

如果你需要在 Linux 上重新开始,请清除当前的 usbfluxd、usbmuxd 和 socat:

sudo killall usbfluxd
sudo systemctl restart usbmuxd
sudo killall socat

使用 https://github.com/sickcodes/osx-optimizer 让容器更快

查看 https://github.com/sickcodes/osx-optimizer 中的命令!

  • 跳过 GUI 登录屏幕(风险自负!)
  • 在 macOS 上禁用 spotlight 索引,以大幅加快 Virtual Instances 的速度。
  • 禁用沉重的登录屏幕壁纸
  • 禁用更新(风险自负!)

通过将 /var/lib/docker 移动到外部驱动器、块存储、NFS 或任何其他可想象的位置来增加磁盘空间。

按照下面的教程移动 /var/lib/docker

  • 使用服务器的磁盘或 SSD,而不是廉价的大容量物理磁盘存储。
  • 块存储、NFS 等。

教程在此:https://sick.codes/how-to-run-docker-from-block-storage/

只有在你愿意清除当前所有 Docker 镜像/层的情况下,才遵循上述教程。

安全模式:暂时禁用 docker,以便你可以暂时移动 Docker 文件夹。

killall dockerd
systemctl disable --now docker
systemctl disable --now docker.socket
systemctl stop docker
systemctl stop docker.socket

现在,Docker 守护进程已关闭,将 /var/lib/docker 移动到某个位置

然后,将 /var/lib/docker 符号链接到某个位置:

mv /var/lib/docker /run/media/user/some_drive/docker
ln -s /run/media/user/some_drive/docker /var/lib/docker

# now check if /var/lib/docker is working still
ls /var/lib/docker

如果你看到文件夹,则说明成功了。你可以重启 Docker,或者如果你想确保万无一失,可以直接重启系统。

重要通知:

2021-11-14 - 添加了 High Sierra、Mojave

构建时选择以下其中一项,使用 docker pull 时无关紧要:

--build-arg SHORTNAME=high-sierra 
--build-arg SHORTNAME=mojave
--build-arg SHORTNAME=catalina
--build-arg SHORTNAME=big-sur
--build-arg SHORTNAME=monterey
--build-arg SHORTNAME=ventura
--build-arg SHORTNAME=sonoma

技术细节

目前存在多个镜像,每个镜像都有不同的用途(详见下文):

  • High Sierra (10.13)
  • Mojave (10.14)
  • Catalina (10.15)
  • Big Sur (11)
  • Monterey (12)
  • Ventura (13)
  • Sonoma (14)
  • Auto(预制的 Catalina)
  • Naked(使用您自己的 .img)
  • Naked-Auto(使用您自己的 .img 并通过 SSH 登录)

High Sierra:

https://img.shields.io/docker/image-size/sickcodes/docker-osx/high-sierra?label=sickcodes%2Fdocker-osx%3Ahigh-sierra

Mojave:

https://img.shields.io/docker/image-size/sickcodes/docker-osx/mojave?label=sickcodes%2Fdocker-osx%3Amojave

Catalina:

https://img.shields.io/docker/image-size/sickcodes/docker-osx/latest?label=sickcodes%2Fdocker-osx%3Alatest

Big Sur:

https://img.shields.io/docker/image-size/sickcodes/docker-osx/big-sur?label=sickcodes%2Fdocker-osx%3Abig-sur

Monterey 制作你自己的镜像:

https://img.shields.io/docker/image-size/sickcodes/docker-osx/monterey?label=sickcodes%2Fdocker-osx%3Amonterey

Ventura 制作你自己的镜像:

https://img.shields.io/docker/image-size/sickcodes/docker-osx/ventura?label=sickcodes%2Fdocker-osx%3Aventura

Sonoma 制作你自己的镜像:

https://img.shields.io/docker/image-size/sickcodes/docker-osx/sonoma?label=sickcodes%2Fdocker-osx%3Asonoma

预制的 Catalina 系统,由 Sick.Codes 提供:用户名:user,密码:alpine

https://img.shields.io/docker/image-size/sickcodes/docker-osx/auto?label=sickcodes%2Fdocker-osx%3Aauto

Naked:自带镜像设置(先使用上述任意一种):

https://img.shields.io/docker/image-size/sickcodes/docker-osx/naked?label=sickcodes%2Fdocker-osx%3Anaked

裸车自动:与上述相同,但包含 -e USERNAME-e PASSWORD 以及 -e OSX_COMMANDS="put your commands here"

https://img.shields.io/docker/image-size/sickcodes/docker-osx/naked-auto?label=sickcodes%2Fdocker-osx%3Anaked-auto

功能

  • 在 Linux 上使用 usbfluxd 通过 iPhone OSX KVM 运行!
  • 在 Linux 上运行 macOS Monterey 虚拟机!
  • 文件夹共享-
  • USB 直通(支持热插拔)
  • 已启用 SSH (localhost:50922)
  • 如果使用 ./vnc 版本,则已启用 VNC (localhost:8888)
  • 通过 序列号生成器! 进行 iMessage 安全研究
  • 已启用 X11 转发
  • 基于 QEMU + KVM 运行
  • 支持 Big Sur、自定义镜像、Xvfb 无头模式
  • 你可以使用 docker commit 克隆你的容器

要求

  • 最低安装需要 20GB+++ 磁盘空间(如果使用 Xcode 则需要 50GB)
  • 应在 BIOS 设置中启用虚拟化
  • 一个支持 kvm 的 x86_64 主机
  • 至少 50 GBs 用于 :auto(一半用于基础镜像,一半用于运行时镜像

待办事项

  • 面向安全研究人员的文档
  • GPU 加速
  • 对 virt-manager 的支持

Docker

基于本仓库内容构建的镜像也可在 Docker Hub 上获取,以便使用:https://hub.docker.com/r/sickcodes/docker-osx

可用 Docker 镜像及其预期用途的完整列表可在 说明 中找到。

Kubernetes

Docker-OSX 支持 Kubernetes。

Kubernetes Helm Chart 和文档可在 helm 目录 下找到。

感谢 cephasara 贡献了这一重要贡献。

Artifact HUB

支持

小问题与故障

如果您在运行 Docker-OSX 时遇到小问题或有任何疑问,请随时提交 issue

已解决的问题

不过,在提交 issue 之前,请先查看 已关闭的 issue,并确认您正在使用本仓库的最新版本——您的问题可能已经得到解决!您也可以在下方 此处 的问答部分找到答案。

功能请求与更新

关注 @sickcodes

专业支持

对于更复杂的需求,我们提供以下支持服务:

  • 企业支持、商业支持或常规支持。
  • 自定义镜像、自定义脚本、咨询(可按小时计费!)
  • 与您或您的开发团队进行一对一交流。

如果您感兴趣,请联系 @sickcodes on Twitter 或点击 此处

许可证/贡献

Docker-OSX 采用 GPL v3+ 许可证。我们欢迎并非常感谢贡献。事实上,您被允许将 Docker-OSX 作为工具来创建专有软件。

其他基于 Docker/QEMU 的有趣项目

免责声明

如果你认真对待 Apple Security,并且有可能在 Apple Bug Bounty Program 中找到六位数的漏洞赏金,那么你来对地方了!更多说明:Hackintosh、OSX-KVM 或 Docker-OSX 合法吗?

本项目中提及的产品名称、徽标、品牌及其他商标均为其各自商标持有人的财产。这些商标持有人与我们的仓库没有任何关联。他们以任何方式都不赞助或认可本项目。

说明

容器镜像

已经设置好或只是想快速创建一个容器?请查看我们的快速入门,或参见我们容器创建示例部分中的更多用例。

有多种不同的 Docker-OSX 镜像可供选择,适用于不同的用途。

使用 :latestbig-sur 创建你的个人镜像。然后,从镜像中拉取该镜像。之后,你将能够复制该镜像并将其导入到 :naked 容器中,以便反复将容器恢复到之前的状态。

初始设置

在做其他任何事情之前,你需要在 BIOS 中开启硬件虚拟化。具体方法取决于你的特定机器(和 BIOS),但应该很简单。

然后,你需要在主机上安装 QEMU 和其他一些依赖项:

# ARCH
sudo pacman -S qemu libvirt dnsmasq virt-manager bridge-utils flex bison iptables-nft edk2-ovmf

# UBUNTU DEBIAN
sudo apt install qemu qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils virt-manager libguestfs-tools

# CENTOS RHEL FEDORA
sudo yum install libvirt qemu-kvm

然后,启用 libvirt 并加载 KVM 内核模块:

sudo systemctl enable --now libvirtd
sudo systemctl enable --now virtlogd

echo 1 | sudo tee /sys/module/kvm/parameters/ignore_msrs

sudo modprobe kvm

我想在 Windows 上运行 Docker-OSX

使用 WSL2(Windows 11 + Windows 子系统 Linux)可以在 Windows 上运行 Docker-OSX。

你必须安装 build 22000+(21H2 或更高版本)的 Windows 11。

首先,在管理员 powershell 中运行此命令在你的计算机上安装 WSL。更多信息,请查看这里

这将默认安装 Ubuntu。

wsl --install

你可以使用 wsl -l -v 在 PowerShell 中确认 WSL2 已启用。要查看其他可用的发行版,请使用 wsl -l -o

如果你之前安装过 WSL1,请升级到 WSL 2。检查此链接以从 WSL1 升级到 WSL2

WSL 安装完成后,前往 C:/Users/<Your_Name>/.wslconfig 并在文件末尾添加 nestedVirtualization=true(如果文件不存在,请创建它)。有关 .wslconfig 文件的更多信息,请查看此链接。请确保在文件资源管理器选项中已选中“显示隐藏文件”和“显示文件扩展名”。 结果应如下所示:

[wsl2]
nestedVirtualization=true

进入你的 WSL 发行版(在 powershell 中运行 wsl),并使用 kvm-ok 命令检查 KVM 是否已启用。输出应如下所示:

INFO: /dev/kvm exists
KVM acceleration can be used

如果尚未安装,请使用命令 sudo apt -y install bridge-utils cpu-checker libvirt-clients libvirt-daemon qemu qemu-kvm 进行安装。

现在,如果尚未安装,请下载并安装 Docker for Windows

安装完成后,进入设置并勾选以下 2 个复选框:

General -> "Use the WSL2 based engine";
Resources -> WSL Integration -> "Enable integration with my default WSL distro", 

确保已安装 x11-apps。如果未安装,请使用命令 sudo apt install x11-apps -y 进行安装。

最后,有 3 种方式获取视频输出:

  • WSLg:这是最简单且易于使用的选项。可能会出现一些问题,例如键盘未完全透传或在桌面上看到第二个鼠标 - WSLg 上的问题 - 但仍推荐此选项。

要使用 WSLg 内置的 X-11 服务器,请将 docker run 命令中的这两行更改为指向 WSLg 的 Docker-OSX。

-e "DISPLAY=${DISPLAY:-:0.0}" \
-v /mnt/wslg/.X11-unix:/tmp/.X11-unix \

或者尝试:

-e "DISPLAY=${DISPLAY:-:0}" \
-v /mnt/wslg/.X11-unix:/tmp/.X11-unix \

对于 Windows 上的 Ubuntu 20.x,请参阅 https://github.com/sickcodes/Docker-OSX/discussions/458

  • VNC: 请参阅 VNC 部分 以获取更多信息。你也可以向 qemu 添加 -vnc 参数。通过 VNC 客户端连接到你的 mac 虚拟机。这里有一个操作指南
  • 桌面环境: 这将为你提供完整的桌面 Linux 体验,但会占用计算机稍多的资源。这里有一个示例指南,但也有其他帮助设置桌面环境的指南。DE 示例

创建你的容器时的额外启动说明

  • 启动 macOS 基础系统(按 Enter 键)

  • 点击 Disk Utility

  • 擦除最大的磁盘(默认约为 200gb),切勿修改较小的磁盘。 -- 如果你无法点击 erase,你可能需要将磁盘大小减少 1kb

  • (可选)使用未使用的空间创建一个分区来容纳操作系统和你的文件,如果你想要限制容量。(对于 Xcode 12,分区至少需要 60gb。)

  • 点击 Reinstall macOS

  • 系统在安装过程中可能需要多次重启

故障排除

常规检查

如果你在启动时遇到困难,这是一个很好的起点,尤其是如果你还不太熟悉 Docker。

只是想快速创建一个容器?查看我们的容器创建示例部分。

更具体/高级的故障排查问题和答案可在 更多问题和答案 中找到。您还应该查看 已关闭的问题。即使您无法在此文档中找到,其他人可能已经得到了类似您问题的解答!

确认您的 CPU 支持虚拟化

参见 初始设置

Docker 未知服务器操作系统错误

docker: unknown server OS: .
See 'docker run --help'.

这意味着你的 docker 守护进程未运行。

pgrep dockerd 应返回空值

因此,你有几种选择。

sudo dockerd 用于前台运行 Docker。我使用此方式。

或者

sudo systemctl --start dockerd 用于立即启动 dockerd。

或者

sudo systemctl --enable --now dockerd 用于在每次重启时启动 dockerd,并立即启动。

使用更多 CPU 核心/SMP

示例:

-e EXTRA='-smp 6,sockets=3,cores=2'

-e EXTRA='-smp 8,sockets=4,cores=2'

-e EXTRA='-smp 16,sockets=8,cores=2'

注意,与内存不同,CPU 使用率是共享的。因此,你可以将所有 CPU 分配给容器。

确认你的用户属于 Docker 组、KVM 组、libvirt 组

将自己添加到 Docker 组

如果你使用 sudo dockerd 或 dockerd 由 systemd/systemctl 控制,则你必须属于 Docker 组。 如果你不属于 Docker 组:

sudo usermod -aG docker "${USER}"

如有需要,也请将自己添加到 kvm 和 libvirt 组:

sudo usermod -aG libvirt "${USER}"
sudo usermod -aG kvm "${USER}"

另请参阅:初始设置

Docker 守护进程是否已启用?

# run ad hoc
sudo dockerd

# or daemonize it
sudo nohup dockerd &

# enable it in systemd (it will persist across reboots this way)
sudo systemctl enable --now docker

# or just start it as your user with systemd instead of enabling it
systemctl start docker

更多问题与解答

衷心感谢我们的贡献者,他们迄今为止已经解决了几乎所有可预见的问题!

https://github.com/sickcodes/Docker-OSX/blob/master/CREDITS.md

稍后启动同一容器(持久化磁盘)

使用 docker run 创建了一个容器,并希望稍后再次复用其底层镜像?

注意:请先参阅 容器创建示例,了解如何到达适用此场景的状态。

这适用于您希望稍后再次运行同一个容器的情况。您可能需要使用 docker commit 在复用之前保存您的容器。使用 docker ps --all 检查您的容器是否已持久化。

如果您不执行此操作,每次都会生成一个新的镜像。

# look at your recent containers and copy the CONTAINER ID
docker ps --all

# docker start the container ID
docker start -ai abc123xyz567

# if you have many containers, you can try automate it with filters like this
# docker ps --all --filter "ancestor=sickcodes/docker-osx"
# for locally tagged/built containers
# docker ps --all --filter "ancestor=docker-osx"

你也可以将 .img 文件从容器中提取出来,该文件存储在 /var/lib/docker 中,并将其作为运行时参数提供给 :naked Docker 镜像。

另请参阅:此处

我之前使用过 Docker-OSX,并希望重启一个自动启动的容器

使用 sickcodes/docker-osx:auto 的容器可以在启动过程中被停止。

# find last container
docker ps -a

# docker start old container with -i for interactive, -a for attach STDIN/STDOUT
docker start -ai -i <Replace this with your ID>

LibGTK 错误 "connection refused"

如果您尚未完成硬件虚拟化的所有配置,可能会看到一个或多个与 libgtk 相关的错误。如果您尚未完成,请查看 initial setup 部分和 routine checks 部分,您可能遗漏了某个配置步骤,或者尚未准备好所有必需的 Docker 依赖项。

另请参阅:here

Permissions denied 错误

如果您尚未配置 xhost,请尝试以下操作:

echo $DISPLAY

# ARCH
sudo pacman -S xorg-xhost

# UBUNTU DEBIAN
sudo apt install x11-xserver-utils

# CENTOS RHEL FEDORA
sudo yum install xorg-x11-server-utils

# then run
xhost +

RAM 超额分配

你无法分配超过机器实际拥有的 RAM。默认值为 3 Gigabytes:-e RAM=3

如果你尝试为容器分配超过当前可用量的 RAM,可能会看到如下错误:cannot set up guest memory 'pc.ram': Cannot allocate memory。另请参阅:此处此处

例如(如下所示),buff/cache 中已包含 20 Gigabytes 的已分配 RAM:

[user@hostname ~]$ free -mh
               total        used        free      shared  buff/cache   available
Mem:            30Gi       3.5Gi       7.0Gi       728Mi        20Gi        26Gi
Swap:           11Gi          0B        11Gi

清除缓冲区与缓存:

sudo tee /proc/sys/vm/drop_caches <<< 3

现在再次检查 RAM:

[user@hostname ~]$ free -mh
               total        used        free      shared  buff/cache   available
Mem:            30Gi       3.3Gi        26Gi       697Mi       1.5Gi        26Gi
Swap:           11Gi          0B        11Gi

PulseAudio

使用 PulseAudio 处理声音

注意:AppleALCalcidVoodooHDA-OC 不支持 codec。然而,IORegistryExplorer 确实显示控制器组件正在工作。

docker run \
    --device /dev/kvm \
    -e AUDIO_DRIVER=pa,server=unix:/tmp/pulseaudio.socket \
    -v "/run/user/$(id -u)/pulse/native:/tmp/pulseaudio.socket" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    sickcodes/docker-osx

PulseAudio 调试

docker run \
    --device /dev/kvm \
    -e AUDIO_DRIVER=pa,server=unix:/tmp/pulseaudio.socket \
    -v "/run/user/$(id -u)/pulse/native:/tmp/pulseaudio.socket" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e PULSE_SERVER=unix:/tmp/pulseaudio.socket \
    sickcodes/docker-osx pactl list

使用 WSLg 的 PulseAudio

docker run \
    --device /dev/kvm \
    -e AUDIO_DRIVER=pa,server=unix:/tmp/pulseaudio.socket \
    -v /mnt/wslg/runtime-dir/pulse/native:/tmp/pulseaudio.socket \
    -v /mnt/wslg/.X11-unix:/tmp/.X11-unix \
    sickcodes/docker-osx

转发额外端口(nginx 托管示例)

根据您的需求,可以转发额外的端口。在本示例中,我们将使用 Mac OSX 来托管 nginx:

host:10023 <-> 10023:container:10023 <-> 80:guest

在主机上,运行:

docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -e ADDITIONAL_PORTS='hostfwd=tcp::10023-:80,' \
    -p 10023:10023 \
    sickcodes/docker-osx:auto

在运行容器的 Terminal 会话中,执行:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

brew install nginx
sudo sed -i -e 's/8080/80/' /usr/local/etc/nginx/nginx.confcd
# sudo nginx -s stop
sudo nginx

nginx 现在应该可以在端口 10023 上访问。

此外,你可以将多条语句串联在一起,例如:

    -e ADDITIONAL_PORTS='hostfwd=tcp::10023-:80,hostfwd=tcp::10043-:443,'
    -p 10023:10023 \
    -p 10043:10043 \

桥接网络

您可能无需对默认配置进行任何操作即可启用容器内部的互联网连接。此外,即使 ping 不起作用,curl 也可能正常工作。

参见此处此处此处 的讨论。

为远程安装的桥接网络连接启用 IPv4 转发

本地安装不需要此操作。

此外请注意,即使您在容器中使用 VPN,这也可能导致主机泄露您的 IP

但是,如果您正在尝试远程连接到 Docker-OSX 实例(例如托管在数据中心中的 Docker-OSX 实例),这可能会提高您的性能:

# enable for current session
sudo sysctl -w net.ipv4.ip_forward=1

# OR
# sudo tee /proc/sys/net/ipv4/ip_forward <<< 1

# enable permanently
sudo touch /etc/sysctl.conf
sudo tee -a /etc/sysctl.conf <<EOF
net.ipv4.ip_forward = 1
EOF

# or edit manually with the editor of your choice
nano /etc/sysctl.conf || vi /etc/sysctl.conf || vim /etc/sysctl.conf

# now reboot

与 Docker-OSX QEMU macOS 共享文件夹

与来宾系统共享文件夹非常简单。

您的文件夹将进入 Arch 容器内的 /mnt/hostshare,然后通过 QEMU 传递。

然后在 mac 内部使用 sudo -S mount_9p hostshare 进行挂载。

例如,

FOLDER=~/somefolder
    -v "${FOLDER}:/mnt/hostshare" \
    -e EXTRA="-virtfs local,path=/mnt/hostshare,mount_tag=hostshare,security_model=passthrough,id=hostshare" \

完整示例:

# stat mac_hdd_ng.img
SHARE=~/somefolder

docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -v "${PWD}/mac_hdd_ng.img:/home/arch/OSX-KVM/mac_hdd_ng.img" \
    -v "${SHARE}:/mnt/hostshare" \
    -e EXTRA="-virtfs local,path=/mnt/hostshare,mount_tag=hostshare,security_model=passthrough,id=hostshare" \
    sickcodes/docker-osx:latest

# !!! Open Terminal inside macOS and run the following command to mount the virtual file system
# sudo -S mount_9p hostshare

将 Linux NFS 驱动器共享到 macOS

要通过 NFS 共享文件夹,请在主机上设置一个文件夹,例如 /srv/nfs/share,然后将其追加到 /etc/exports

/srv/nfs/share      127.0.0.1/0(insecure,rw,all_squash,anonuid=1000,anongid=985,no_subtree_check)

您可能需要现在重新加载导出,这将开始共享该目录。

# reload shared folders
sudo exportfs -arv

来源与说明

anonuidanongid 授予共享文件夹的权限,其中 anonuidanongid 需与您的 linux 用户相匹配;id -u

id -u ; id -g 将输出 userid:groupid

chown 1000:985 /srv/nfs/share
chmod u+rwx /srv/nfs/share

使用附加标志 --network host 启动 Docker-OSX 容器

在 mac 终端中创建并挂载 nfs 文件夹:

mkdir -p ~/mnt
sudo mount_nfs -o locallocks 10.0.2.2:/srv/nfs/share ~/mnt

通过 QEMU 将 USB 驱动器共享到 macOS

挂载 USB 驱动器(热插拔/热插 USB)

启动您的容器。

选择一个端口,例如,7700

lsusb 以获取 vid:pid

在 Linux 上: sudo usbredirserver -p 7700 1e3d:2096

现在,在 Docker 窗口中按 Enter 键以查看 (qemu) 控制台。

即使机器已启动,您也可以使用如下命令添加/移除磁盘:

chardev-add socket,id=usbredirchardev1,port=7700,host=172.17.0.1

device_add usb-redir,chardev=usbredirchardev1,id=usbredirdev1,debug=4

在 macOS 启动时挂载 USB 驱动器到 Docker OSX

PORT=7700
IP_ADDRESS=172.17.0.1

-e EXTRA="-chardev socket,id=usbredirchardev1,port=${PORT},host=${IP_ADDRESS} -device usb-redir,chardev=usbredirchardev1,id=usbredirdev1,debug=4" \`

Fedora:通过桥接网络启用互联网连接

Fedora 的默认防火墙设置可能会阻止 Docker 的网络接口访问互联网。为了解决此问题,你需要在防火墙中将该接口加入白名单:

# Set the docker0 bridge to the trusted zone
sudo firewall-cmd --permanent --zone=trusted --add-interface=docker0
sudo firewall-cmd --reload

嵌套硬件虚拟化

检查您的机器是否已启用硬件虚拟化:

sudo tee /sys/module/kvm/parameters/ignore_msrs <<< 1

egrep -c '(svm|vmx)' /proc/cpuinfo

虚拟网络适配器

快速互联网连接

-e NETWORKING=vmxnet3

互联网连接缓慢

-e NETWORKING=e1000-82545em

CI/CD 相关改进

减小镜像大小的技巧

  • 像往常一样启动容器,并删除不必要的文件。一种有用的 方法是使用 du -sh */ 目录开始,并查找 可以删除文件的大目录。例如不必要的缓存文件、 Xcode 平台等。
  • 一旦你对释放的空间量感到满意,使用 sudo trimforce enable 启用 trim,然后重启。
  • 使用 dd if=/dev/zero of=./empty && rm -f empty 将磁盘上的空闲空间清零
  • 关闭虚拟机并使用 docker cp stoppedcontainer:/home/arch/OSX-KVM/mac_hdd_ng.img . 复制出 qcow 镜像
  • 运行 qemu-img check -r all mac_hdd_ng.img 以修复任何错误。
  • 运行 qemu-img convert -O qcow2 mac_hdd_ng.img deduped.img 并再次检查错误
  • 可选: 运行 qemu-img convert -c -O qcow2 deduped.img compressed.img 以进一步压缩镜像。这可能会降低运行时速度,但应将大小减少约 25%。
  • 再次检查错误,并构建一个新的 docker 镜像。例如使用此 Dockerfile
FROM sickcodes/docker-osx
USER arch
COPY --chown=arch ./deduped.img /home/arch/OSX-KVM/mac_hdd_ng.img

使用 Telnet 无头运行 Docker-OSX

首先确保 autoboot 已启用

接下来,你需要设置 SSH 以自动启动。

sudo systemsetup -setremotelogin on

确保提交新的 docker 镜像并保存,或按照减少磁盘空间]一节中的说明重新构建。

然后使用以下参数运行它。

# Run with the -nographic flag, and enable a telnet interface
  docker run \
    --device /dev/kvm \
    -p 50922:10022 \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e EXTRA="-monitor telnet::45454,server,nowait -nographic -serial null" \
    mycustomimage

在本地构建 Docker-OSX 时,使用哪些镜像源是合适的?

如果你要在本地构建 Docker-OSX,你可能希望使用 Arch Linux 的镜像源。

镜像源位置可在此处找到(使用两位国家代码):https://archlinux.org/mirrorlist/all/

docker build -t docker-osx:latest \
    --build-arg RANKMIRRORS=true \
    --build-arg MIRROR_COUNTRY=US \
    --build-arg MIRROR_COUNT=10 \
    --build-arg SHORTNAME=catalina \
    --build-arg SIZE=200G .

自定义 QEMU 参数(直通设备)

使用便捷的运行时参数提供程序选项 -e EXTRA=,将任意设备/目录传递给 Docker 容器及 QEMU 参数。

# example customizations
docker run \
    -e RAM=4 \
    -e SMP=4 \
    -e CORES=4 \
    -e EXTRA='-usb -device usb-host,hostbus=1,hostaddr=8' \
    -e INTERNAL_SSH_PORT=23 \
    -e MAC_ADDRESS="$(xxd -c1 -p -l 6 /dev/urandom | tr '\n' ':' | cut -c1-17)" \
    -e AUDIO_DRIVER=alsa \
    -e IMAGE_PATH=/image \
    -e SCREEN_SHARE_PORT=5900 \
    -e DISPLAY=:0 \
    -e NETWORKING=vmxnet3 \
    --device /dev/kvm \
    --device /dev/snd \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    docker-osx:latest

生成序列号

./custom 中生成序列号,或者让 docker 在运行时生成它们(见下文)。

在任何时候,登录 iCloud 等之前,请验证您的序列号。

# this is a quick way to check your serial number via cli inside OSX
ioreg -l | grep IOPlatformSerialNumber

# test some commands
sshpass -p 'alpine' ssh user@localhost -p 50922 'ping google.com'

# check your serial number
sshpass -p 'alpine' ssh user@localhost -p 50922 'ioreg -l | grep IOPlatformSerialNumber'

开始使用序列号

# ARCH
pacman -S libguestfs

# UBUNTU DEBIAN
apt install libguestfs -y

# RHEL FEDORA CENTOS
yum install libguestfs -y

./custom 文件夹中,您将找到 4 脚本。

  • config-nopicker-custom.plist
  • opencore-image-ng.sh

这两个文件来自 OSX-KVM。

你不需要修改这两个文件。

config.plist 中有 5 个值被替换为占位符。点击此处查看这些值,没有理由。

  • generate-unique-machine-values.sh 此脚本将生成序列号,附带 Mac 地址,并输出到 CSV/TSV,同时生成一个 bootdisk image

你可以创建数百个,./custom/generate-unique-machine-values.sh --help

./custom/generate-unique-machine-values.sh \
    --count 1 \
    --tsv ./serial.tsv \
    --bootdisks \
    --output-bootdisk OpenCore.qcow2 \
    --output-env source.env.sh

或者,如果你有一些特定的序列号……

  • generate-specific-bootdisk.sh
generate-specific-bootdisk.sh \
    --model "${DEVICE_MODEL}" \
    --serial "${SERIAL}" \
    --board-serial "${BOARD_SERIAL}" \
    --uuid "${UUID}" \
    --mac-address "${MAC_ADDRESS}" \
    --output-bootdisk OpenCore-nopicker.qcow2

此示例在运行时以无头模式生成一组随机序列号

# proof of concept only, generates random serial numbers, headlessly, and quits right after.
docker run --rm -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -e NOPICKER=true \
    -e GENERATE_UNIQUE=true \
    -e DEVICE_MODEL="iMacPro1,1" \
    sickcodes/docker-osx:auto

# -e OSX_COMMANDS='ioreg -l | grep IOPlatformSerialNumber' \

此示例在运行时生成一组特定的序列号

# run the same as above 17gb auto image, with SSH, with nopicker, and save the bootdisk for later.
# you don't need to save the bootdisk IF you supply specific serial numbers!

docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -e NOPICKER=true \
    -e GENERATE_SPECIFIC=true \
    -e DEVICE_MODEL="iMacPro1,1" \
    -e SERIAL="C02TW0WAHX87" \
    -e BOARD_SERIAL="C027251024NJG36UE" \
    -e UUID="5CCB366D-9118-4C61-A00A-E5BAF3BED451" \
    -e MAC_ADDRESS="A8:5C:2C:9A:46:2F" \
    -e OSX_COMMANDS='ioreg -l | grep IOPlatformSerialNumber' \
    sickcodes/docker-osx:auto

此示例在运行时使用您现有的图像,以 1000x1000 显示分辨率生成一组特定的序列号

# run an existing image in current directory, with a screen, with SSH, with nopicker.

stat mac_hdd_ng.img # make sure you have an image if you're using :naked

docker run -it \
    -v "${PWD}/mac_hdd_ng.img:/image" \
    --device /dev/kvm \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -p 50922:10022 \
    -e NOPICKER=true \
    -e GENERATE_SPECIFIC=true \
    -e DEVICE_MODEL="iMacPro1,1" \
    -e SERIAL="C02TW0WAHX87" \
    -e BOARD_SERIAL="C027251024NJG36UE" \
    -e UUID="5CCB366D-9118-4C61-A00A-E5BAF3BED451" \
    -e MAC_ADDRESS="A8:5C:2C:9A:46:2F" \
    -e WIDTH=1000 \
    -e HEIGHT=1000 \
    sickcodes/docker-osx:naked

如果你想生成序列号,可以在运行时使用 -e GENERATE_UNIQUE=true \

或者你可以在 ./custom 文件夹中生成它们。然后使用:

    -e GENERATE_SPECIFIC=true \
    -e SERIAL="" \
    -e BOARD_SERIAL="" \
    -e UUID="" \
    -e MAC_ADDRESS="" \

使序列号在重启后持久化


stat mac_hdd_ng_testing.img
touch ./output.env

# generate fresh random serial numbers, with a screen, using your own image, and save env file with your new serial numbers for later.

docker run -it \
    --device /dev/kvm \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -p 50922:10022 \
    -e NOPICKER=true \
    -e GENERATE_UNIQUE=true \
    -e GENERATE_SPECIFIC=true \
    -e DEVICE_MODEL="iMacPro1,1" \
    -v "${PWD}/output.env:/env" \
    -v "${PWD}/mac_hdd_ng_testing.img:/image" \
    sickcodes/docker-osx:naked

要使用 iMessage 或 iCloud,您需要更改 5 值。

  • SERIAL
  • BOARD_SERIAL
  • UUID
  • MAC_ADDRESS

ROM 只是小写的 mac 地址,每个单词之间没有 :

你可以让容器为你生成它们,使用 -e GENERATE_UNIQUE=true

或者让容器使用特定的值,使用 -e GENERATE_SPECIFIC=true

    -e GENERATE_SPECIFIC=true \
    -e DEVICE_MODEL="iMacPro1,1" \
    -e SERIAL="C02TW0WAHX87" \
    -e BOARD_SERIAL="C027251024NJG36UE" \
    -e UUID="5CCB366D-9118-4C61-A00A-E5BAF3BED451" \
    -e MAC_ADDRESS="A8:5C:2C:9A:46:2F" \

更改显示分辨率

显示分辨率由以下行控制:

https://github.com/sickcodes/Docker-OSX/blob/master/custom/config-nopicker-custom.plist#L819

Docker-OSX 不会挂载该磁盘,而是使用这个巧妙的技巧生成一个新的 OpenCore.qcow2

-e GENERATE_UNIQUE=true \
-e WIDTH=800 \
-e HEIGHT=600 \

要使用 WIDTH/HEIGHT,必须与 -e GENERATE_UNIQUE=true-e GENERATE_SPECIFIC=true 一起使用。

由于需要使用 libguestfs 创建新的启动分区,启动时间将延长约 30 秒。

-e GENERATE_SPECIFIC=true \
-e WIDTH=1920 \
-e HEIGHT=1080 \
-e SERIAL="" \
-e BOARD_SERIAL="" \
-e UUID="" \
-e MAC_ADDRESS="" \

更改 Docker-OSX 分辨率示例

# using an image in your current directory
stat mac_hdd_ng.img

docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v "${PWD}/mac_hdd_ng.img:/image" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e GENERATE_SPECIFIC=true \
    -e DEVICE_MODEL="iMacPro1,1" \
    -e SERIAL="C02TW0WAHX87" \
    -e BOARD_SERIAL="C027251024NJG36UE" \
    -e UUID="5CCB366D-9118-4C61-A00A-E5BAF3BED451" \
    -e MAC_ADDRESS="A8:5C:2C:9A:46:2F" \
    -e MASTER_PLIST_URL=https://raw.githubusercontent.com/sickcodes/Docker-OSX/master/custom/config-nopicker-custom.plist \
    -e WIDTH=1600 \
    -e HEIGHT=900 \
    sickcodes/docker-osx:naked
# generating random serial numbers, using the DIY installer, along with the screen resolution changes.
docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e GENERATE_UNIQUE=true \
    -e WIDTH=800 \
    -e HEIGHT=600 \
    sickcodes/docker-osx:latest

这里还有几种其他分辨率!如果你的分辨率无效,它将默认为 800x600。

    -e WIDTH=800 \
    -e HEIGHT=600 \
    -e WIDTH=1280 \
    -e HEIGHT=768 \
    -e WIDTH=1600 \
    -e HEIGHT=900 \
    -e WIDTH=1920 \
    -e HEIGHT=1080 \
    -e WIDTH=2560 \
    -e HEIGHT=1600 \

本示例展示了如何在容器创建后更改分辨率。

第一步是停止 docker 守护进程

sudo systemctl stop docker

第二步是修改容器配置

/var/lib/docker/containers/[container-id]/config.v2.json

(假设你原始的 WIDTH 为 1024,HEIGHT 为 768,你可以搜索 1024 并将其替换为新值。768 同理。)

最后一步是重启 docker 守护进程

sudo systemctl restart docker

在 Mac OSX 中挂载物理磁盘

将磁盘作为卷传入容器,然后再次将磁盘传入 QEMU 命令行附加参数中。

使用 config-custom.plist,因为你可能希望看到启动菜单,否则省略第一行:

DISK_TWO="${PWD}/mount_me.img"
-e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom.plist' \
-v "${DISK_TWO}:/disktwo" \
-e EXTRA='-device ide-hd,bus=sata.5,drive=DISK-TWO -drive id=DISK-TWO,if=none,file=/disktwo,format=qcow2' \

物理磁盘挂载示例

OSX_IMAGE="${PWD}/mac_hdd_ng_xcode_bigsur.img"
DISK_TWO="${PWD}/mount_me.img"

docker run -it \
    --device /dev/kvm \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom.plist' \
    -v "${OSX_IMAGE}":/image \
    -v "${DISK_TWO}":/disktwo \
    -e EXTRA='-device ide-hd,bus=sata.5,drive=DISK-TWO -drive id=DISK-TWO,if=none,file=/disktwo,format=qcow2' \
    sickcodes/docker-osx:naked

另请参阅:此处

在 Linux 上提取 APFS 磁盘

在 Docker-OSX 中,我们使用的是 qcow2 镜像。

这意味着镜像会随着你的使用而增长,但客户机操作系统认为你有 200GB 可用空间。

只读

# mount the qemu image like a real disk
sudo modprobe nbd max_part=8
sudo qemu-nbd --connect=/dev/nbd0 ./image.img
sudo fdisk /dev/nbd0 -l

mkdir -p ./mnt
sudo mount /dev/nbd0p1 ./mnt

# inspect partitions (2 partitions)
sudo fdisk /dev/nbd0 -l

# mount using apfs-linux-rw OR apfs-fuse
mkdir -p ./part

sudo mount /dev/nbd0p2 ./part
sudo apfs-fuse -o allow_other /dev/nbd0p2 ./part

当您完成对磁盘的检查后,可以卸载分区、磁盘并移除回环设备:

sudo umount ./part
sudo umount ./mnt
sudo qemu-nbd --disconnect /dev/nbd0
sudo rmmod nbd

USB 直通

首先,QEMU 必须以 root 身份启动。

通过更改容器内设备的权限,也有可能实现 USB 直通。 参见 此处

例如,使用以下内容创建一个新的 Dockerfile

FROM sickcodes/docker-osx
USER arch
RUN sed -i -e s/exec\ qemu/exec\ sudo\ qemu/ ./Launch.sh
COPY --chown=arch ./new_image.img /home/arch/OSX-KVM/mac_hdd_ng.img

其中 new_image.img 是您提取的 qcow2 镜像。然后使用 docker build . 进行重建

接下来,我们需要找出要传递给虚拟机的 USB 设备的总线和端口号:

lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
    |__ Port 2: Dev 5, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 2: Dev 5, If 1, Class=Chip/SmartCard, Driver=, 12M
    |__ Port 3: Dev 2, If 0, Class=Wireless, Driver=, 12M
    |__ Port 3: Dev 2, If 1, Class=Wireless, Driver=, 12M
    |__ Port 5: Dev 3, If 0, Class=Video, Driver=uvcvideo, 480M
    |__ Port 5: Dev 3, If 1, Class=Video, Driver=uvcvideo, 480M

在本示例中,我们想要透传一个智能卡设备。我们想要的设备位于总线 1 和端口 2。

如果你的设备是 usb 2.0 (ehci) 与 usb 3.0 (xhci),也可能存在差异。 参见 此处 以获取更多详细信息。

# hostbus and hostport correspond to the numbers from lsusb
# runs in privileged mode to enable access to the usb devices.
docker run \
  --privileged \
  --device /dev/kvm \
  -e RAM=4 \
  -p 50922:10022 \
  -e "DISPLAY=${DISPLAY:-:0.0}" \
  -e EXTRA="-device virtio-serial-pci -device usb-host,hostbus=1,hostport=2" \
  mycustomimage

在 MacOS shell 中执行 system_profiler SPUSBDataType 时,你应该能看到设备出现。

重要提示:在虚拟机运行期间,这将导致主机系统失去对该 USB 设备的访问权限!

容器创建示例

快速启动你自己的镜像(裸容器镜像)

这是我最喜欢的容器。你可以提供一个现有的磁盘镜像作为 Docker 命令行参数。

  • 使用 sudo find /var/lib/docker -name mac_hdd_ng.img -size +10G 拉取镜像

  • 使用命令参数 -v "${PWD}/mac_hdd_ng.img:/image" 提供你自己的本地镜像,并在指示 Docker 创建容器时使用 sickcodes/docker-osx:naked

    • 裸镜像用于启动任何现有的 .img 文件,例如当前工作目录中的文件($PWD

    • 默认情况下,此镜像有一个名为 NOPICKER 的变量,其值为 "true"。这会跳过磁盘选择菜单。使用 -e NOPICKER=false 或除单词 true 以外的任何字符串来进入启动菜单。

      这允许你使用其他磁盘,而不是跳过启动菜单,例如恢复磁盘或磁盘工具。

docker pull sickcodes/docker-osx:naked

# run your own image + SSH
# change mac_hdd_ng.img
docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v "${PWD}/mac_hdd_ng.img:/image" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    sickcodes/docker-osx:naked

# run local copy of the auto image + SSH + Boot menu
docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v "${PWD}/mac_hdd_ng_auto.img:/image" \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e "NOPICKER=false" \
    sickcodes/docker-osx:naked

构建具有视频输出的 OSX 容器

快速入门命令应开箱即用,前提是您保留以下行。适用于 autonaked 机器:

    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \

带有任意命令行参数的预构建镜像

https://img.shields.io/docker/image-size/sickcodes/docker-osx/auto?label=sickcodes%2Fdocker-osx%3Aauto

-e OSX_COMMANDS 允许你在容器内运行任何命令

docker pull sickcodes/docker-osx:auto

# boot to OS X shell + display + specify commands to run inside OS X!
docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e "OSX_COMMANDS=/bin/bash -c \"put your commands here\"" \
    sickcodes/docker-osx:auto

# Boots in a minute or two!

或者,如果你已经拥有一张图片,并且只想登录并执行任意命令:

docker pull sickcodes/docker-osx:naked-auto

# boot to OS X shell + display + specify commands to run inside OS X!
docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e USERNAME=yourusername \
    -e PASSWORD=yourpassword \
    -e "OSX_COMMANDS=/bin/bash -c \"put your commands here\"" \
    sickcodes/docker-osx:naked-auto

# Boots in a minute or two!

更多示例

存在大量其他潜在用例,它们可以与 Docker-OSX 完美配合,其中一些将在下文展示!

构建无头 OSX 容器

对于无头容器,请从您的 docker run 命令中删除以下两行:

    # -v /tmp/.X11-unix:/tmp/.X11-unix \
    # -e "DISPLAY=${DISPLAY:-:0.0}" \

从自定义镜像构建无头容器

https://img.shields.io/docker/image-size/sickcodes/docker-osx/naked?label=sickcodes%2Fdocker-osx%3Anaked

这对于 CI/CD 流水线尤其有帮助。

# run your own image headless + SSH
docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    -v "${PWD}/mac_hdd_ng.img:/image" \
    sickcodes/docker-osx:naked

构建一个允许在 localhost 上使用不安全 VNC 的无头容器(!仅限本地使用!)

必须将 -it 更改为 -i,才能与 QEMU 控制台进行交互

要退出使用 -i 的容器,你必须 docker kill <containerid>。例如,要终止所有进程,docker ps | xargs docker kill

原生 QEMU VNC 示例

docker run -i \
    --device /dev/kvm \
    -p 50922:10022 \
    -p 5999:5999 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e EXTRA="-display none -vnc 0.0.0.0:99,password=on" \
    sickcodes/docker-osx:big-sur

# type `change vnc password myvncusername` into the docker terminal and set a password
# connect to localhost:5999 using VNC
# qemu 6 seems to require a username for vnc now

完全没有使用 TLS/HTTPS 加密!

或者 ssh -N root@1.1.1.1 -L 5999:127.0.0.1:5999,其中 1.1.1.1 是你的远程服务器 IP。

(注意:如果你关闭端口 5999 并使用 SSH 隧道,这就变得安全了。)

构建一个无头容器以通过安全 VNC 远程运行

添加以下行:

-e EXTRA="-display none -vnc 0.0.0.0:99,password=on"

在 Docker 终端中,按 enter 直到看到 (qemu)

输入 change vnc password someusername

为你的新 vnc 用户名^ 设置一个密码。

你还需要容器 IP:docker inspect <containerid> | jq -r '.[0].NetworkSettings.IPAddress'

或者 ip n 通常会首先显示容器 IP。

现在 VNC 使用 Docker 容器 IP 进行连接,例如 172.17.0.2:5999

通过 SSH 进行远程 VNC:ssh -N root@1.1.1.1 -L 5999:172.17.0.2:5999,其中 1.1.1.1 是你的远程服务器 IP,172.17.0.2 是你的局域网容器 IP。

现在你可以直接通过 VNC 连接到任何使用此命令构建的容器!

我想使用 SPICE 而不是 VNC

可选地,你可以启用 SPICE 协议,它允许使用 remote-viewer 访问你的 OSX 容器,而不是 VNC。

注意:-disable-ticketing 将允许未经身份验证的访问 VM。请参阅 spice 手册 以获取设置身份验证访问(“Ticketing”)的帮助。

  docker run \
    --device /dev/kvm \
    -p 3001:3001 \
    -p 50922:10022 \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    -e EXTRA="-monitor telnet::45454,server,nowait -nographic -serial null -spice disable-ticketing,port=3001" \
    mycustomimage

然后只需执行 remote-viewer spice://localhost:3001 并添加 --spice-debug 用于调试。

基于已配置和设置好的容器创建镜像

# You can create an image of an already configured and setup container.
# This allows you to effectively duplicate a system.
# To do this, run the following commands

# make note of your container id
docker ps --all
docker commit containerid newImageName

# To run this image do the following
docker run \
    --device /dev/kvm \
    --device /dev/snd \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    newImageName
docker pull sickcodes/docker-osx:auto

# boot directly into a real OS X shell with no display (Xvfb) [HEADLESS]
docker run -it \
    --device /dev/kvm \
    -p 50922:10022 \
    sickcodes/docker-osx:auto

# username is user
# password is alpine
# Wait 2-3 minutes until you drop into the shell.

运行 Docker-OSX 的原始版本


docker pull sickcodes/docker-osx:latest

docker run -it \
    --device /dev/kvm \
    --device /dev/snd \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e "DISPLAY=${DISPLAY:-:0.0}" \
    sickcodes/docker-osx:latest

# press CTRL + G if your mouse gets stuck
# scroll down to troubleshooting if you have problems
# need more RAM and SSH on localhost -p 50922?

运行但在 OS X 中启用 SSH(原始版本)!

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

# turn on SSH after you've installed OS X in the "Sharing" settings.
ssh user@localhost -p 50922

安装完所有内容后自动启动 OS X

添加额外选项 -e NOPICKER=true

旧机器:

# find your containerID
docker ps

# move the no picker script on top of the Launch script
# NEW CONTAINERS
docker exec containerID mv ./Launch-nopicker.sh ./Launch.sh

# VNC-VERSION-CONTAINER
docker exec containerID mv ./Launch-nopicker.sh ./Launch_custom.sh

# LEGACY CONTAINERS
docker exec containerID bash -c "grep -v InstallMedia ./Launch.sh > ./Launch-nopicker.sh
chmod +x ./Launch-nopicker.sh
sed -i -e s/OpenCore\.qcow2/OpenCore\-nopicker\.qcow2/ ./Launch-nopicker.sh
"

安装后 big-sur 镜像启动缓慢。这是预期行为吗?

容器设置中的自动更新仍处于开启状态。您可能希望将其关闭。我们对此有未来的开发计划。

什么是 ${DISPLAY:-:0.0}

$DISPLAY 是指向您的 X11 显示服务器的 shell 变量。

${DISPLAY} 的作用相同,但允许您像这样连接变量:

  • 例如,${DISPLAY}_${DISPLAY} 会打印 :0.0_:0.0
  • 例如,$DISPLAY_$DISPLAY 会打印 :0.0

...因为 $DISPLAY_ 不是 $DISPLAY

${variable:-fallback} 允许您设置一个“回退”变量,当 $variable 未设置时进行替换。

您还可以使用 ${variable:=fallback} 来设置该变量(在您当前的终端中)。

在 Docker-OSX 中,我们假设 :0.0 是您的默认 $DISPLAY 变量。

您可以查看您的

echo $DISPLAY

这样,${DISPLAY:-:0.0} 将使用你的 X11 服务器为你设置的任何变量,否则 :0.0

什么是 -v /tmp/.X11-unix:/tmp/.X11-unix

-v 是一个 Docker 命令行选项,允许你将一个卷传递给容器。

我们让 Docker 容器使用的目录是一个 X 服务器显示套接字。

/tmp/.X11-unix

如果我们让 Docker 容器使用与我们自身环境相同的显示套接字,那么在 Docker 容器内运行的任何应用程序也会显示在你的屏幕上!https://www.x.org/archive/X11R6.8.0/doc/RELNOTES5.html

启动或创建容器时出现 ALSA 错误

在初始化或启动进入容器时,你可能会在 (qemu) 控制台中看到如下形式的错误: ALSA lib blahblahblah: (function name) returned error: no such file or directory。这些错误或多或少是预期之中的。只要你能启动进入容器且一切运行正常,就没有理由为此担心。

另请参阅:此处