darwin-jail
darwin-jail
是一个构建 Darwin chroot 目录的工具(jail),可以抽取一个纯净的 jail
环境,以便能够在其中定制构建一些服务。这种jail环境是原生 macOS 系统,所以可以用来作为可移植的容器环境来使用,例如部署一些需要的工具和服务,并且一次部署,后续可以多次使用。
警告
实际构建的 darwinjail
环境还是比较占用空间的, Sequoia 15.2 上构建占用了 7.3G
( 我尝试在新安装虚拟机macOS中完成,但 darwinjail
只复制基础目录,确实占据了 7.3G
)。
还远远比不上 FreeBSD Jail 灵活的 FreeBSD Thin(薄) Jail (基于 ZFS 或 NullFS)。但是能够打包镜像,并且储备用于其他工作环境,还是比较有意思的。
准备工作
完成 Homebrew初始化 : 建议安装完
XCode command line tools
并完成所有 Homebrew 需要的软件之后再制作darwin-jail
,这样能够完整包含所需工具以及依赖库。
部署和使用
(这步我现在通过调整
darwin-jails
配置来完辰统一打包)建议先安装 XCode command line tools,然后打包/Library/Developer/CommandLineTools
目录
这样不仅具备了 C (gcc是clang的别名),也包含了 Swift ,就不需要在 Homebrew 中再安装llvm了 - 参考 如何在 mac 电脑上轻量化地写C
不过,在 darwin-jail
中执行 gcc --version
提示信息:
gcc --version
提示信息提示错误gcc: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead
xcrun: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead
Apple clang version 16.0.0 (clang-1600.0.26.6)
Target: x86_64-apple-darwin24.2.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
这个报错是因为 getconf DARWIN_USER_TEMP_DIR
就有提示错误 getconf: confstr: DARWIN_USER_TEMP_DIR: Input/output error
我在正常的环境中执行上述命令,可以到哪看到 DARWIN_USER_TEMP_DIR
对应的目录 /var/folders/fb/1zwz4_152_g8lv6w4m6zq78r0000gn/T/
,实际上是因为在jail中无法写入 /var/folders
导致的报错
则在jail中也补上:
sudo mkdir -p /var/folders/fb/1zwz4_152_g8lv6w4m6zq78r0000gn/T/
sudo chown -R huatai:staff /var/folders/fb/1zwz4_152_g8lv6w4m6zq78r0000gn
执行:
# 下载
git clone git@github.com:darwin-containers/darwin-jail.git
cd darwin-jail/
# 建议修订 darwinjail/mkjail.files 配置文件,将
# /Library/Developer/CommandLineTools 和 /usr/local 也一起打包
# 准备chroot目录
jail_dir="/Users/admin/jails/sequoia"
sudo python3 -m darwinjail "$jail_dir"
# 进入chroot
#sudo chroot "$jail_dir"
sudo chroot -u admin "$jail_dir" /bin/zsh
为了在chroot中能够使用DNS,执行:
sudo mkdir -p "$jail_dir/var/run"
# link 命令现在不支持 -f 参数
sudo link /var/run/mDNSResponder "$jail_dir/var/run/mDNSResponder"
备注
chroot
目录中没有包含用户目录,也没有用户账号,所以需要 macOS用户账号命令行 创建(但是我目前执行创建错误 Operation failed with error: eParameterError
待排查)
怎么搞定普通用户账号?没有普通用户账号,运行 Homebrew 是个大问题:
解决方法是使用 sudo chroot -u admin
来执行,这样进入chroot环境后就是指定用户 admin
补充工作
将 Homebrew初始化 制作的
brew.tar.gz
复制到 jail 根目录下解压缩配置
~/.zprofile
:
# 激活Homebrew
eval "$(/usr/local/bin/brew shellenv)"
# 在jail中df命令无法获取jail外的目录挂载属性
alias df='df -h 2>/dev/null'
# 设置Locale
export LC_ALL=en_US.UTF-8
# 设置curl代理
# export http_proxy=socks5h://localhost:1080
export http_proxy=http://localhost:3128
export https_proxy=$http_proxy
export no_proxy=localhost,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
配置
~/.gitconfig
:
[http]
#proxy = socks5h://127.0.0.1:1080
version = HTTP/1.1
proxy = http://127.0.0.1:3128
postBuffer = 524288000
lowSpeedLimit = 0
lowSpeedTime = 999999
由于jail无法访问外部数据,对于需要处理的数据目录需要存放到jail中,然后在外面建立一个软链接方便查看 需要 bindfs 进行目录映射
需要进一步学习 macOS APFS命令行
一些限制和问题
无法在
chroot
环境中使用 tmux多会话终端管理 和screen
:tmux
直接退出,screen
则提示错误Must be connected to a terminal.
参考 How do I use the terminal SCREEN when chrooted? ,需要将 /dev/pts
(pseudo-terminal文件系统 devpts
挂载到chroot内部。不过,方法是针对Linux的,我没有找到macOS下方法。
将Darwin rootfs作为Docker镜像
安装
crane
工具制作镜像
brew install crane
# You might first need to authenticate using
# sudo crane auth login "$registry" -u "$username" -p "$password"
sudo bash -c 'crane append --oci-empty-base -t "$image_tag" -f <(tar -f - -c -C "$jail_dir" .)'
备注
crane
是 GitHub: google/go-containerregistry 中包含的一个工具.
A Tale of Two Container Image Tools: Skopeo and Crane 介绍了容器镜像工具