首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Apple Container Machine:把 Linux 搬进 Mac

Apple Container Machine:把 Linux 搬进 Mac

作者头像
乱世不浮生
发布2026-06-18 09:34:53
发布2026-06-18 09:34:53
210
举报

TL;DR

container machine 是 Apple Container 里容易被忽视的另一半:不是跑一个进程,而是跑一个完整的 Linux 开发环境,自动挂载你的 macOS $HOME,支持 systemd,用法更接近 WSL2 而不是 Docker。

从货箱到书房:Container Machine 是什么

这个系列已经写了四篇:

读完这四篇,你对 Apple Container 的印象大概是:每个容器独立一个 VM,container run nginx:latest 起来就是一个跑在 VM 里的 nginx 进程,用法和 Docker 接近。

Apple Container[1] 从 0.1.0 开始就带着另一个子命令:`container machine`[2]。它很少被提及,文档也相对简短。

container machine 做的事情,用一句话说是:把一个完整的 Linux 系统跑起来,而不只是跑一个进程

具体来说,启动一个 container machine 时:

  • VM 里运行的是镜像自带的 init 系统(比如 systemd),而不是苹果自己的极简 `vminitd`[3]
  • 你的 macOS 用户名和 $HOME 目录自动挂载进去,不需要任何配置
  • 进入环境后,你就是你——用户名不变,/Users/<username> 就是你在 Mac 上的家目录

这和普通容器有本质的区别。普通容器是应用模型:给一个进程一个隔离的执行环境,跑完就结束。container machine环境模型:把一个完整的 Linux 系统搬进来,Mac 是客厅,Linux 是书房,两间房之间的门永远开着。

在整个 Apple Container 系列里,这篇文章处理的是第四块拼图:框架介绍 → 普通容器入门 → 演进评估 → 开发环境。如果你在 Mac 上有「想直接用 Linux 工具链,但不想维护一台虚拟机」的需求,container machine 就是为这个场景设计的。

Container vs Container Machine:两种模式

二者底层用的是同一套引擎——都是 OCI 镜像,都是独立轻量 VM,都通过同一个 CLI 管理。区别只在启动时的引导方式:

  • container run → 忽略镜像的 init,直接拉起 entrypoint 进程,跑完即止
  • container machine create → 把引导权交给镜像自带的 init 系统(如 systemd),整个 Linux 环境活起来

同一个 Ubuntu 镜像,两种用法,两种结果。

container run

container machine

定位

应用模型:跑单个进程/服务

环境模型:完整 Linux 开发环境

init 系统

vminitd(Apple 自研,极简)

镜像自带(如 systemd)

macOS $HOME

不挂载

自动挂载,零配置

用户身份

root 或镜像内用户

自动匹配宿主机用户名

生命周期

进程结束即退出

持久化,显式 stop

典型场景

CI、跑服务、测试

日常开发环境

和 Docker 的关系

container rundocker run 在精神上是同一件事:进程/应用模型,无状态,entrypoint 驱动。如果你只用过这一半,觉得 Apple Container 就是「原生的 Docker 替代」,也没错——但你只用了一半。

container machine 反而更接近 WSL2[4](Windows)或 Lima[5](Mac 上的前辈方案):持久化的 Linux 环境,和宿主机文件系统打通,可以 systemctl 管服务。

和 VMware Fusion 的关系

表面上 container machineVMware Fusion[6] 最像——都跑完整 Linux,都有 systemd,都持久化。但有一个本质差异:

VMware Fusion 是历史积累型。你在里面装软件、改配置,VM 本身随时间变得越来越「你的」,状态不可复现,坏了就头疼。

container machine 是声明型。环境由 Dockerfile 定义,出问题了 container machine rm 删掉重建一个,和新的一模一样。你的文件在 Mac 的 $HOME 里,一根毛没少。

核心区别不是重量,是环境和数据的关系:VMware Fusion 把环境和数据混在一起,都住在 VM 里;container machine 把二者分离——环境是声明出来的,数据在 Mac 上。这一点,它更接近 devcontainer[7] 的精神:用一个 Dockerfile 或配置文件描述开发环境,环境本身可抛弃、可重建、可分享给团队,代码和数据始终在宿主机上。

快速上手

前提是已经安装好 Apple Container 并启动了服务。如果还没安装,从 GitHub releases 页面[8] 下载最新的签名安装包(当前为 1.0.0),双击安装后执行:

代码语言:javascript
复制
container system start

注意:官方目前只支持 macOS 26,macOS 15 上发现的问题不再修复。安装完整步骤可参考 开箱实践[9],但注意文中版本信息已过时。

创建并进入第一个 machine

代码语言:javascript
复制
container machine create alpine:latest --name dev

创建好之后,直接进交互 shell:

代码语言:javascript
复制
container machine run -n dev

进去之后跑两条命令验证一下:

代码语言:javascript
复制
whoami   # 输出你的 macOS 用户名,不是 root
pwd      # /Users/<你的用户名>,就是你的 Mac home 目录

这两行的输出结果,是 container machine 和普通容器最直观的差别——你不是在一个陌生的 Linux 里,你带着自己的身份和文件进来了。

也可以不进 shell,直接在 machine 里跑单条命令:

代码语言:javascript
复制
container machine run -n dev uname -a
container machine run -n dev -- cat /proc/cpuinfo   # 命令带 flag 时加 --

container machine run 启动时如果 machine 处于停止状态,会自动先把它启动起来,不需要手动 start

设置默认 machine

每次都带 -n dev 有点烦,可以设一个默认:

代码语言:javascript
复制
container machine set-default dev

之后直接 container machine run 就操作 dev,不需要再指定名字。

常用命令

生命周期管理

代码语言:javascript
复制
container machine ls              # 列出所有 machine
container machine inspect dev     # 查看详细信息(JSON)
container machine stop dev        # 停止
container machine rm dev          # 删除,同时清除持久化存储

调整资源

代码语言:javascript
复制
container machine set -n dev cpus=4 memory=8G
container machine stop dev
container machine run -n dev -- nproc   # 验证生效

资源调整在下次启动后生效,改完记得 stop 再 run。默认内存是宿主机内存的一半。

挂载模式也可以调整,$HOME 的挂载方式支持三种:

  • rw(默认):可读写,Mac 和 Linux 两侧实时同步
  • ro:只读,Linux 里不能写入 Mac 的文件
  • none:不挂载,machine 和宿主机文件系统完全隔离
代码语言:javascript
复制
container machine set -n dev home-mount=ro

m 缩写

machine 有个别名 m,所有子命令都能用:

代码语言:javascript
复制
container m ls
container m run
container m stop dev
container m set -n dev cpus=4 memory=8G

敲起来省事不少,尤其是高频操作 container m run 几乎和 ssh 进虚拟机一样顺手。

自带 Linux 服务:systemd 实战

这是 container machine 和普通容器差别最大的地方。普通容器里你跑不起来 systemd——vminitd 只负责拉起 entrypoint,没有 service 管理的概念。但 container machine 用的是镜像自带的 init,只要镜像里有 /sbin/initsystemd 就能完整运行。

alpine 镜像没有 systemd,要体验这个能力需要自己构建一个支持 systemd 的镜像。官方文档给了一个 Ubuntu 24.04 的 Dockerfile:

代码语言:javascript
复制
FROM ubuntu:24.04

ENV container container

RUN apt-get update && \
    apt-get install -y \
    dbus systemd openssh-server net-tools iproute2 iputils-ping curl wget vim-tiny man sudo && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    yes | unminimize

RUN >/etc/machine-id
RUN >/var/lib/dbus/machine-id

RUN systemctl set-default multi-user.target
RUN systemctl mask \
      dev-hugepages.mount \
      sys-fs-fuse-connections.mount \
      systemd-update-utmp.service \
      systemd-tmpfiles-setup.service \
      console-getty.service
RUN systemctl disable \
      networkd-dispatcher.service

RUN sed -i -e 's/^AcceptEnv LANG LC_\*$/#AcceptEnv LANG LC_*/' /etc/ssh/sshd_config

几个关键点:

  • >/etc/machine-id>/var/lib/dbus/machine-id:清空 machine-id,让系统首次启动时自动生成唯一 ID,避免多个 machine 共用相同标识
  • systemctl mask:屏蔽掉几个在虚拟化环境里会导致启动卡住的 unit
  • systemctl set-default multi-user.target:不起图形界面,直接到命令行

构建并创建:

代码语言:javascript
复制
container build --dns 8.8.8.8 -t local/ubuntu-machine:latest .
container machine create local/ubuntu-machine:latest --name ubuntu
container machine run -n ubuntu

构建时容器内默认没有可用的 DNS,apt-get update 会因无法解析域名而失败。加上 --dns 8.8.8.8 可以解决。

进去之后,就是一个完整的 Ubuntu 环境,可以用 systemd 管理服务:

代码语言:javascript
复制
sudo systemctl start ssh
sudo systemctl status ssh
sudo systemctl start postgresql   # 装好之后直接 start

和在一台真实的 Linux 机器上没有区别。

自定义镜像与用户初始化

镜像要求

任何 Linux 镜像,只要根目录下有 /sbin/init,就可以用作 container machine 的底座。不一定要 systemd,其他 init 系统(如 OpenRC)也行。

用户初始化

第一次启动时,container machine 会自动运行一个内置脚本,在 Linux 里创建和宿主机用户名、UID、GID 完全匹配的用户。这就是为什么进去之后 whoami 直接是你自己。

如果内置的初始化逻辑不够用——比如你想在用户创建的同时装 sudo 权限、写入 SSH 公钥、配置 dotfiles——可以在镜像里放一个自定义脚本:

代码语言:javascript
复制
/etc/machine/create-user.sh

这个脚本在首次启动时以 root 身份执行一次,可以拿到以下环境变量:

变量

含义

CONTAINER_USER

用户名

CONTAINER_UID

用户 ID

CONTAINER_GID

组 ID

CONTAINER_HOME

home 目录路径

CONTAINER_MACHINE_ID

machine 标识符

一个实用的例子——创建用户并配置 sudo:

代码语言:javascript
复制
#!/bin/sh
useradd -m -u "$CONTAINER_UID" -g "$CONTAINER_GID" "$CONTAINER_USER"
echo "$CONTAINER_USER ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

脚本只跑一次,之后重启不会重复执行。如果你想重置用户初始化,container machine rm 掉重建即可——这也是「声明型环境」的好处,状态清晰,没有历史包袱。

小结

container machine 和普通容器共用同一套引擎,但解决的是完全不同的问题。

普通容器的答案是:给一个进程一个干净的执行环境。container machine 的答案是:把 Linux 搬进来,Mac 上的文件不用动,身份不用切换,用完环境坏了删掉重建,代码还在。

这个设计在 1.0.0 的 release notes 里被专门点名——Apple 显然认为它是这个项目值得关注的能力。如果你在 Mac 上有「需要真实 Linux 环境」的场景,不管是跑 systemd 服务、测试多发行版兼容性,还是单纯想要一个不污染 Mac 的开发沙箱,container machine 都值得试一试。

毕竟比起养一台 VMware 虚拟机,container machine run 要顺手得多。

参考资料

  • container machine 官方文档[10]
  • Apple Container GitHub[11]
  • Apple Containerization Framework[12]
  • 苹果发布 Containerization Framework:开启 macOS 容器化新纪元[13]
  • Apple Container 开箱实践[14]
  • Apple Container 0.8.0:从初生到成熟的七个月演进之路[15]

参考资料

[1]

Apple Container: https://github.com/apple/container

[2]

container machine: https://github.com/apple/container/blob/main/docs/container-machine.md

[3]

vminitd: https://github.com/apple/containerization

[4]

WSL2: https://learn.microsoft.com/windows/wsl/

[5]

Lima: https://lima-vm.io/

[6]

VMware Fusion: https://www.vmware.com/products/fusion.html

[7]

devcontainer: https://containers.dev/

[8]

GitHub releases 页面: https://github.com/apple/container/releases

[9]

开箱实践: https://atbug.com/apple-container-hands-on/

[10]

container machine 官方文档: https://github.com/apple/container/blob/main/docs/container-machine.md

[11]

Apple Container GitHub: https://github.com/apple/container

[12]

Apple Containerization Framework: https://github.com/apple/containerization

[13]

苹果发布 Containerization Framework:开启 macOS 容器化新纪元: https://atbug.com/apple-containerization-framework-macos-release/

[14]

Apple Container 开箱实践: https://atbug.com/apple-container-hands-on/

[15]

Apple Container 0.8.0:从初生到成熟的七个月演进之路: https://atbug.com/apple-container-evolution-seven-months-journey/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 乱世不浮生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • TL;DR
  • 从货箱到书房:Container Machine 是什么
  • Container vs Container Machine:两种模式
    • 和 Docker 的关系
    • 和 VMware Fusion 的关系
  • 快速上手
    • 创建并进入第一个 machine
    • 设置默认 machine
  • 常用命令
    • 生命周期管理
    • 调整资源
    • m 缩写
  • 自带 Linux 服务:systemd 实战
  • 自定义镜像与用户初始化
    • 镜像要求
    • 用户初始化
  • 小结
  • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档