container
当你还不能对自己说今天学到了什么东西时,你就不要去睡觉。——利希顿堡
https://github.com/apple/container
当 Mac 遇见 Linux 容器:Apple container 让轻量虚拟机学会了优雅奔跑
在开发者的世界里,容器一直像一位高效、干练、说干就干的工程师。它不拖泥带水,不讲排场,只想把应用打包、带走、运行,然后继续奔赴下一场任务。
而在 Mac 的世界里,尤其是在 Apple silicon 的土地上,这位工程师终于等来了一个很懂它的新搭档:Apple container。
container 是 Apple 推出的一个工具,用来在 Mac 上创建和运行 Linux 容器。它把 Linux 容器放进轻量级虚拟机里运行,既保留了容器的灵活轻快,又借助虚拟化能力带来了更贴合 macOS 环境的运行方式。它用 Swift 编写,并且专门为 Apple silicon 优化。换句话说,它不是“也能跑”,而是从出生起就知道自己该怎么在苹果芯片上把事情做漂亮。
如果把传统容器工具比作一群四处打工、适应力极强的旅行者,那么 Apple container 更像是一位穿着剪裁合身西装的本地向导。它不只是把你带到目的地,还会告诉你这条路为什么顺、风为什么正、脚下的地板为什么刚好适合起飞。
它到底是什么
Apple 对这个项目的描述非常明确:container 是一个可以在 Mac 上创建和运行 Linux 容器的工具,这些容器运行在轻量级虚拟机中。它使用 Swift 编写,针对 Apple silicon 做了优化。
这句话看起来平静,实际上信息量很大。
先看“Linux 容器”。这意味着它并不是一个另起炉灶、自成一派的新格式,而是站在开发者已经熟悉的容器生态之上。
再看“轻量级虚拟机”。这意味着它没有把容器粗暴地硬塞进宿主系统,而是给它准备了一个既轻盈又清爽的小房间。容器住进去,既能自在工作,也能拥有更清晰的运行边界。
最后看“针对 Apple silicon 优化”。这就像 Apple 在对 M 系列芯片说:这位新朋友不是路过的,它是来长期定居、深度适配、认真生活的。
它为什么让人眼前一亮
很多人第一次看到 container,都会觉得它像是 Apple 对容器世界递出的一张名片:简洁、克制、工程感强,而且很懂平台本身。
它最吸引人的地方,不只是“Apple 也做了容器工具”,而是它选择了一条非常 Apple 的路径:
- 不跟你争论容器是不是虚拟机
- 不跟你炫耀复杂抽象层有多厚
- 不试图把所有事情都变成一场配置项狂欢
它只是认真地告诉你:我能在 Mac 上创建和运行 Linux 容器,我消费和产出 OCI 兼容镜像,我可以从标准镜像仓库拉取镜像,也可以把构建好的镜像推送回去。
这就很重要了。
因为 OCI 兼容意味着它能和标准容器镜像生态沟通。它不是把自己锁进苹果花园的小工具,而是愿意说通用语言的成员。你熟悉的镜像、熟悉的仓库、熟悉的工作流,都有机会在这里延续生命。
它像一个很有礼貌的新同事,第一天来团队就说:
“你们不用为了我重写全部流程,我会尽量先学会你们已经在说的话。”
这样的工具,很难不让人产生好感。
它背后站着谁
container 并不是凭空出现的。它的底层能力建立在 Apple 的 Containerization Swift 包之上,这个包负责更底层的容器、镜像和进程管理。
这意味着 container 并不只是一个孤零零的命令行工具,它背后其实站着一整套更扎实的技术基础。你看到的是命令,命令背后则是一套有组织、有设计、有边界的实现。
这也让它多了一层气质:它不是一时兴起的实验,而是一个有架构意识的项目。像一位表面安静、实际上骨架非常硬朗的角色,话不多,但做事有章法。
它适合谁
如果你符合下面这些画像,那你大概率会对 container 很感兴趣:
- 你使用 Apple silicon 的 Mac
- 你希望在本机更自然地运行 Linux 容器
- 你关心容器体验和 macOS 平台之间的结合方式
- 你喜欢命令行工具的清晰与直接
- 你愿意尝试 Apple 在开发基础设施方向上的新表达
它特别像是为这样一群开发者准备的:
一边写 macOS 或 iOS,一边也写服务端;
一边享受苹果硬件带来的顺滑,一边又不愿意离开 Linux 工具链;
一边讲究体验,一边又非常看重工程可控性。
container 对这样的人来说,不只是一个工具,更像是一座桥。桥的一头是 Mac 的世界,桥的另一头是 Linux 容器生态。过去你得自己想办法搭临时浮桥,现在 Apple 亲自把桥墩打好了。
运行它需要什么
这里有一个很重要的前提:你需要一台搭载 Apple silicon 的 Mac。
同时,container 依赖 macOS 26,因为它使用了这个版本中虚拟化和网络方面的新特性与增强能力。官方也明确表示不支持更旧版本的 macOS。
这件事其实很 Apple。
它不会为了“广泛兼容”而把自己拽回旧时代,而是更愿意基于最新的平台能力,把事情做得更彻底。它像一个对舞台有要求的表演者,不是在任意地板上都能跳,而是在最适合它的灯光和场地里,把动作完成到位。
所以如果你的设备和系统条件符合要求,那么恭喜,你面对的是一个原生气息很强的容器工具。
如果不符合,那也别急,这不是你不够好,只是这位新朋友暂时还住在更新一点的街区。
安装它,像和一台安静但很能干的机器握手
container 的初始安装方式很直接:从 GitHub Releases 页面下载最新的已签名安装包,然后双击安装。安装过程中,系统会提示输入管理员密码,以便将文件放到 /usr/local 等需要权限的位置。
安装完成后,还需要启动系统服务:
1 | container system start |
这条命令很像清晨按下总电源开关。
在那之前,工具只是静静地待在你的电脑里;在那之后,它才真正开始呼吸。你可以把它想象成一座小型港口的开闸时刻,吊臂抬起,码头点灯,来往的镜像和容器开始有了停靠与起航的能力。
升级、降级、卸载,也都有章可循
一个成熟的工具,不只是能安装成功,还要懂得如何优雅地变化、退场、回滚。
在升级或降级之前,需要先停止当前运行中的 container:
1 | container system stop |
升级到最新版本可以直接运行:
1 | /usr/local/bin/update-container.sh |
如果想降级,需要先卸载当前版本。保留用户数据时使用 -k,删除用户数据时使用 -d:
1 | /usr/local/bin/uninstall-container.sh -k |
完成后,再重新启动系统服务:
1 | container system start |
而当你想彻底卸载它时,也有现成脚本可用。
删除工具以及用户数据:
1 | /usr/local/bin/uninstall-container.sh -d |
保留用户数据,方便以后重新安装时接续使用:
1 | /usr/local/bin/uninstall-container.sh -k |
这部分非常能体现项目的性格。它不是那种“只负责让你装上,剩下你自己想办法”的工具。它像一位收纳习惯很好的人,不但会把东西摆出来,也会告诉你怎么整理、怎么搬家、怎么离场时不留狼藉。
它会说 OCI 这门通用语言
容器世界最怕什么?
最怕自说自话。
而 container 在这一点上让人放心:它消费和产出 OCI 兼容镜像。这意味着它能从任何标准容器注册表拉取镜像,也能把镜像推送回这些标准仓库。
这点看似基础,实际上是整个生态协作的命门。
因为开发者不想被困在一个无法流通的体系里。你今天构建的镜像,明天可能要进 CI,后天可能要进测试环境,下周可能还要被推到团队统一仓库。如果格式和生态不能对话,再优雅的本地体验也会变成一座漂亮却孤独的玻璃房。
而 container 显然明白这件事。
它没有把门锁上,它把门做成了标准尺寸。
从快速开始里,能看到它的性格
官方 README 的快速开始部分不长,但很有代表性。它没有塞满大段概念解释,而是迅速把你带到一个可操作的世界里。
先启动系统服务:
1 | container system start |
然后你就可以继续跟着文档走向更深入的使用路径,包括教程、命令参考、技术概览和 how-to 文档。
这种节奏很像一个靠谱的向导:
“先把车点着,别急着把地图一口气背完。路上我再告诉你该往哪看。”
这比一开始就把你埋进概念堆里,要友好得多。
它不只会跑容器,它还会经营一台容器机器
container 仓库里有一个很有意思的示例:使用 container machine 在 Mac 上创建一个持久化的 Linux 环境,并结合 Visual Studio Code 进行远程开发。
这部分内容特别迷人,因为它让人看见 container 不只是“运行一下容器”那么简单。它还想告诉你:如果你愿意,我可以给你准备一整块顺手的 Linux 开发空间。
创建一台容器机器的命令非常直白:
1 | container machine create --name mymachine --set-default alpine:3.22 |
查看已有机器:
1 | container machine ls |
直接在机器里运行 Linux 命令:
1 | container machine run uname -a |
如果只看这些命令,你会觉得它像是在说:
“你不一定每次都需要一艘一次性小船。
如果你愿意,我也可以给你一间长期可住、随时能进的工作室。”
这就是 container machine 的魅力。它让容器式体验不再只是一次性的运行快照,而更像是一个持续存在的 Linux 工作空间。对开发者来说,这种感觉很舒服,因为很多工作并不是“一次运行完就结束”,而是需要反复进入、修改、调试、观察。
在 Mac 上开发 Linux 应用,这件事 suddenly 变得顺滑了
官方示例里,container machine 和 VS Code Remote - SSH 的组合尤其值得一提。
它展示的是这样一种画面:
你坐在一台 Mac 前,手握熟悉的键盘、触控板、窗口系统和编辑器;但你写下的代码、调试的程序、运行的命令,却发生在一个真实的 Linux 容器机器里。
这像什么呢?
像你人在阳台喝咖啡,手却能伸进隔壁那间专业实验室里拧螺丝,而且动作自然得像在自家厨房切菜。
示例中,先为机器配置 SSH:
1 | cat >> ~/.ssh/config <<EOT |
再创建一个本地域名解析作用域:
1 | sudo container system dns create machine |
然后构建镜像:
1 | container build -t ubuntu-machine:latest -f Dockerfile . |
基于镜像创建默认机器:
1 | container machine create --set-default --name ubuntu ubuntu-machine:latest |
设置 SSH 登录密码:
1 | container machine run -it sudo passwd $(whoami) |
验证 DNS:
1 | ping -c 1 ubuntu.machine |
进入机器:
1 | container machine run |
这一整套流程读下来,你会发现 container 并不是只把容器“跑起来”就算了。它开始关心开发者和环境之间的关系,关心本机目录、用户身份、编辑器接入、网络可达性、远程调试这些真实而琐碎的事情。
一个工具一旦开始认真处理这些细节,它就不再只是一个命令集合,而开始有了“工作流参与者”的身份。
它甚至很懂“开发不是只会启动程序”
在这个 VS Code 示例里,还有一段很打动人的细节:macOS 工作目录和用户名,会自然映射到容器机器中。
示例中先在 Mac 上执行:
1 | pwd |
再进入容器机器里:
1 | container machine run |
这说明什么?
说明 container machine 不想把你和你的工作方式硬生生拆开。它没有用一种陌生感很强的方式强迫你适应,而是尽可能让你觉得:我还在我熟悉的位置,只是脚下这块地板已经悄悄切换成 Linux 了。
这种体验非常妙。
它像舞台布景快速旋转,但演员站位没变。你仍然是你,目录还是那个目录,用户名还是那个用户名,只是后台系统已经换成了另一种运行世界。
对开发者来说,这种“连续感”比单纯的性能数字更珍贵。
一个真实的开发场景,从镜像构建到调试运行
示例继续往下走,甚至演示了如何在容器机器里开发一个 Swift 服务端项目。
先克隆项目:
1 | cd ${HOME} |
然后通过 VS Code Remote - SSH 连接到 ubuntu.machine,安装 Swift 扩展,打开项目目录,观察语言服务构建,再在终端中验证系统环境:
1 | uname -s |
构建项目:
1 | swift build |
之后再配置调试器,启动程序,并从 Mac 终端发出请求:
1 | curl http://ubuntu.machine:8080/todos |
返回结果类似这样:
1 | [{"id":"BDAD25BA-8F52-4A7A-B98D-319AD86179B7","contents":"example todo"}] |
这一系列步骤像一部很流畅的小电影。
镜头一开始是 Mac 桌面,接着切到 Linux 环境里的构建输出,再切到编辑器里的断点,最后回到本机终端里的一次 HTTP 请求。整个过程没有强烈的割裂感,反而像不同空间之间配合默契的交响。
container 在这里扮演的角色,不是喧宾夺主的主角,而是一位极其专业的舞台监督。它不抢镜,但每个灯光点亮的时间都很准确。
清理现场,它也不含糊
当你不再需要这台容器机器时,官方也给出了清晰的清理命令:
1 | container machine stop ubuntu |
删除测试项目:
1 | rm -rf swift-server-todos-tutorial |
移除 SSH 配置:
1 | awk -v h="ubuntu.machine" '/^Host /{skip=($2==h)} !skip' ~/.ssh/config > /tmp/.sshconf && mv /tmp/.sshconf ~/.ssh/config |
移除本地 DNS 条目:
1 | sudo container system dns delete machine |
好的工具,从不把“收尾”当成小事。
它知道,真正的专业不是把东西堆起来,而是用完之后也能把现场恢复得干干净净。像一个有修养的来客,离开时不仅关灯,还顺手把椅子推回桌下。
它身上有一种很少见的气质
看过很多开发工具后,你会发现有些工具天生“重”,有些工具天生“散”,还有一些工具虽然强大,却经常让人觉得自己像在操作一台情绪不稳定的工业设备。
而 container 给人的感觉不是这样。
它很新,但不轻浮。
它很底层,但不粗糙。
它很平台化,但没有把自己做成密不透风的黑盒。
它像一个刚登场却已经站得很稳的角色。语气克制,步伐精准,不喊口号,但你知道它后劲很足。
尤其是对 Apple silicon 用户来说,它不是“容器也能在这儿跑”的替代方案,而更像是“容器本来就该以这种方式在这里生活”的一种表达。
项目状态也说得很坦诚
README 里还特别说明:container 项目目前处于活跃开发中。无论是作为 Swift package 使用,还是作为 container 工具本身使用,其稳定性只在补丁版本范围内得到保证。
这是一种很负责任的态度。
它没有假装自己已经到了坚不可摧的终极形态,而是诚实地告诉你:我正在快速成长,请带着理解和预期来接近我。
这反而会让开发者更愿意信任它。
因为最怕的不是项目还在发展,而是项目明明还在长身体,却非要摆出一副“我已经天下无敌”的样子。container 没这么做。它像一个认真工作的年轻工程师,清楚自己的阶段,也愿意继续把能力一层层打磨出来。
如果你第一次上手,可以这样开始
如果你想用最短路径感受一下它的气质,可以按这个节奏试试:
1 | container system start |
然后继续阅读官方教程和命令参考,逐步体验镜像构建、容器运行、容器机器、远程开发这些能力。
如果你喜欢从命令感受工具的性格,可以优先试试这些方向:
1 | container system start |
这些命令像是一组简短的自我介绍。
第一句说“我能启动和停止系统服务”。
第二句说“我会构建镜像”。
第三句说“我不只会跑容器,我还能给你准备机器”。
第四句说“我还愿意把状态展示得清清楚楚”。
对于一个命令行工具来说,能把自己的能力说得既简练又完整,其实已经很迷人了。
为什么值得关注
Apple container 值得关注,不只是因为它来自 Apple,也不只是因为它面向容器。
更重要的是,它让人看见了一种新的组合方式:
- 用 Apple 擅长的平台整合能力来重新表达容器体验
- 用 Swift 构建面向基础设施的工具
- 用轻量级虚拟机承接 Linux 容器运行
- 用 OCI 兼容性保持对主流生态的连接
- 用容器机器补足持续性开发环境的场景
这不是简单地把已有方案换个壳,而是带着鲜明平台视角重新整理问题。
你能感觉到它在说:
“容器这件事,我不是来重复一遍别人已经写好的答案。
我是想在 Mac 上,把这道题重新做得更顺一点、更自然一点、更像这个平台本该有的样子一点。”
这份野心,很有看头。
最后想说
如果说容器世界是一支常年奔跑的队伍,那么 Apple container 就像新加入的一位跑者。它上场不算最早,却有很清晰的跑姿;它没有吵着让全场立刻看向自己,但每一步都踩得很稳。
它来自 Apple silicon 的主场,住在 macOS 26 的新街区里,手里握着 Swift 写成的工具箱,背后站着 Containerization 的底层支撑,还愿意和 OCI 生态继续好好说话。
它不像一个只为展示技术而生的项目。
它更像一个准备认真参与开发日常的新伙伴。
你可以把它看成 Mac 上 Linux 容器的一位新管家。
也可以把它看成容器和轻量虚拟机之间的一位翻译。
还可以把它看成 Apple 对开发者基础设施的一次郑重表态。
总之,当你在 Apple silicon 的 Mac 上敲下 container system start 的那一刻,像是轻轻推开了一扇门。
门后站着一个很安静的家伙,冲你点点头,说:
来吧,Linux 容器的事,我可以陪你在这台 Mac 上认真做。
