Где боль
Tim Sneath назвал container machines «sleeper hit» WWDC — фичей, которую недооценят на анонсе, а распробуют позже. Легко отмахнуться: ну ещё один способ гонять контейнеры на маке, очередная обёртка от Apple. Но если так прочитать, то и польза, и весь смысл проходят мимо — потому что Apple решает не ту задачу, что Docker.
Задача, которую разработчик на маке решал годами, звучит так: «мне нужен Linux, а железо и ОС — нет». Ответом был Docker Desktop, и у его модели есть конкретная цена. Все контейнеры живут внутри одной большой общей Linux-VM; изоляция между ними — это namespaces и cgroups поверх общего ядра, а не настоящие границы. Каждый bind-mount твоего кода в эту VM идёт через прослойку и стоит производительности на файловых операциях. И внутри контейнера ты, как правило, root в эфемерной среде, которая исчезает после exit вместе со всем, что ты в ней донастроил.
Apple в проекте apple/container ломает первое же допущение этой модели — что хост-VM одна. И поверх этой архитектуры строит «машину», которую действительно легко спутать с контейнером, хотя это другой объект. Чтобы понять, в чём подвох и где реальная польза, надо сначала развести два понятия.
Что такое машина
Container machine — это быстрая, лёгкая и персистентная Linux-среда на Apple silicon, собранная из обычного OCI-образа. Формулировка из доки дословно:
«Container machines are fast, lightweight and persistent. They are based on standard OCI images that can be built and shared. Host integrations such as automatic user and home directory sharing provide quick and easy access to your Linux environment.»
Ключевое слово — persistent. На WWDC 2026 (session 389, «Discover container machines») это сформулировали через пару противопоставлений: «быстрая и лёгкая, как контейнер, и персистентная, как виртуалка». То есть машина берёт скорость старта от контейнера и долгую жизнь от VM.
Под капотом это работает на той же архитектуре, что весь проект container: отдельная лёгкая виртуалка на каждый контейнер и каждую машину, а не одна общая на всех. Реализовано через Swift-фреймворк apple/containerization поверх Virtualization.framework. README дословно: «Containerization executes each Linux container inside of its own lightweight virtual machine». При этом старт остаётся sub-second (WWDC 2025 session 346, «Meet Containerization»).
Базовый набор команд:
container machine create alpine:latest --name dev # создать машину
container machine run -n dev # интерактивный shell
container machine run -n dev whoami # разовая команда
container machine ls # список
container machine stop dev # остановить (состояние сохраняется)
container machine set -n dev cpus=4 memory=8G # ресурсы
m ls # m — алиас container machineМашина vs контейнер
Разница не в реализации, а в модели. Контейнер моделируется вокруг одного приложения; машина — вокруг целой Linux-системы. Из доки дословно: «Containers are typically modeled after an application. A container machine is modeled after a Linux environment. It runs the image’s init system allowing you to register long running services or test your application under a process supervisor.»
Главное здесь — «runs the image’s init system». Обычный контейнер в apple/container поднимает минимальный кастомный Swift-init (vminitd) и запускает в нём ровно один процесс. Машина запускает настоящую init-систему образа — systemd, — а значит в ней работают долгоживущие сервисы и супервизор процессов: systemctl start postgresql поднимет базу как системный сервис, и она переживёт твою сессию.
Второе отличие — состояние. Машина stateful: WWDC дословно — «A Container machine is stateful and persists modifications made while you are working in it», и «Container machine ensures your environment can continue where you left it». Остановил container machine stop, вернулся через день, продолжил с того же места. Контейнер же одноразовый: после выхода всё, что ты в нём наставил, исчезает.
Где проходит граница
| Контейнер | Машина | |
|---|---|---|
| Моделируется вокруг | одного приложения | целой Linux-среды |
| Init | минимальный vminitd, один процесс | init-система образа (systemd) |
| Долгоживущие сервисы | нет | да — systemctl start postgresql |
| Состояние | эфемерное, гибнет на exit | сохраняется между сессиями |
| Жизненный цикл | run → exit | start / stop с продолжением |
Твой $HOME внутри | монтируешь руками | монтируется автоматически |
| Под кем работаешь | обычно root | под своим хостовым юзером |
Чем это меняет DX
Самое заметное для разработчика — автомаппинг юзера и home-директории. Дословно: «A container machine automatically maps your username and home directory into the Linux environment. Your repositories and dotfiles are available on both platforms. Use editors and tools directly on macOS simultaneously building and running your application inside of the Linux environment.»
Разворачивается это в несколько практических вещей:
- Один источник правды для кода. Репозитории лежат в
$HOME, видны и на macOS, и в Linux одновременно. Редактируешь в Cursor или VS Code на маке — собираешь нативным Linux-тулчейном внутри машины. Никакогоdocker cp, никакого rsync, никакой синхронизации.whoamiвнутри отдаёт твоё хостовое имя, а неroot;pwd— твою же рабочую директорию с мака. Монтирование по умолчанию read-write, переключается флагом--home-mount ro|none. - dotfiles едут с тобой. Конфиги шелла, git, редактора уже на месте. Машина ощущается как продолжение твоей среды, а не как голый контейнер, который надо обживать заново.
- Персистентный dev-бокс. Поднял Postgres и Redis как systemd-сервисы — они живут между сессиями. Это сценарий Vagrant и dev-containers, но первой стороной от Apple и без обвязки.
- Изоляция уровня VM на каждую машину при быстром старте. Это намеренный выбор Apple, причём в первую очередь по безопасности. WWDC 2025 дословно: «our goal was to provide the same level of isolation used by the large virtual machines and apply that to each and every container that is started». Полная аппаратная граница вокруг каждой машины, а не общее ядро.
Фактически это «Lima или dev-container, но нативно, с человеческим UX из коробки и без прослойки между твоим кодом и Linux».
Замена Docker или нет
Короткий ответ: нет, это дополнение, а не убийца — по крайней мере сегодня. И дело не в том, что Apple «не дотянула», а в том, что это инструмент другого жанра.
Сравним архитектуры в лоб. Docker Desktop держит все контейнеры в одной большой общей Linux-VM (сейчас это Docker VMM или Apple Virtualization framework; QEMU и HyperKit задепрекейчены) и изолирует их namespaces и cgroups на общем ядре. Apple — по виртуалке на контейнер, с аппаратной изоляцией каждого. Это разный компромисс: Apple покупает изоляцию и нативную скорость ФС ценой памяти, Docker — плотность ценой общего ядра.
Чего Apple-стеку не хватает, чтобы закрыть Docker целиком:
- Compose-аналога для оркестрации мульти-сервисных стеков одной командой.
- Зрелой работы с произвольными OCI-реестрами и какой-либо Kubernetes-интеграции.
- Кроссплатформенности. Только Apple silicon и только macOS 26. Ни Intel-маков, ни Linux- и Windows-хостов. Docker, OrbStack, Colima, podman работают где угодно — а CI у тебя почти наверняка на Linux.
- Зрелости сети (см. ниже).
Важная деталь по позиционированию: формулировка «альтернатива Docker» — от третьих сторон, не от Apple. В материалах самой Apple Docker не упоминается ни разу. Apple продаёт «нативную Linux-среду для разработки на Mac», а не «убийцу Docker» — и это честнее отражает, чем вещь является.
У выбранной архитектуры есть и обратная сторона: модель «одна VM на контейнер» прожорлива по памяти при рое контейнеров — критику озвучивал Anil Madhavapeddy (DevClass). Для машин-как-dev-боксов, которых у тебя две-три, это не так больно, как для двадцати эфемерных контейнеров.
Требования и грабли
Требования жёсткие. Нужен macOS 26 Tahoe — README прямо говорит: «We do not support older versions of macOS». На macOS 15 Sequoia базовое запустится, но сеть сильно урезана: нет связи контейнер-контейнер, один общий vmnet, баг с рассогласованием подсети. И только Apple silicon — Intel-маки не поддерживаются вовсе.
Подтверждённые баги (зафиксированы на CLI v0.2.0 — про статус в 1.0.0 см. оговорку):
- Ping наружу не работает. ICMP-исходящий из контейнера даёт 100% потерь пакетов, при том что DNS резолвится нормально — issue #345, открыт. То есть
apk addи пуллы образов идут, аping google.comмолчит. - VPN ломает сеть контейнеров. Запущенный на хосте Tailscale, Mullvad, Cloudflare WARP или GlobalProtect рвут связность: MTU контейнерного
eth0(1280) не сходится с VPN-овскимutun, плюс перехват маршрутов и конфликт за порт 53 под DNS. Лечится только ручными обходами черезpfиroute. У Docker Desktop тут на практике лучше — есть штатные ручки MTU. #345, #817. - Rosetta-эмуляция x86 спотыкается. setuid-бинарь
sudoпри сборке--arch amd64падает сPermission denied, тогда как нативная aarch64-сборка того же Dockerfile проходит — issue #116.
Оговорки
- Свежесть критична. Баги выше зафиксированы на v0.2.0, а релиз 1.0.0 вышел 9 июня 2026 — за день до того, как это собрано. Закрыты ли #345, #116, #817 в 1.0.0, по живым источникам я не подтвердил: research брал их как доказательство существования класса проблем, а не как актуальную карту. Прежде чем на что-то закладываться, перепроверь эти три issue на дату 1.0.0.
- Что не верифицировалось отдельными фактами. Конкретные feature-гэпы против Docker (Compose, реестры, Kubernetes) — это рамка рассуждения, а не индивидуально доказанные пункты. Бенчмарков скорости и цифр по расходу памяти в источниках нет.
- Tim Sneath в материалах фигурирует как человек, связанный с проектом, но его роль и точные слова я как отдельный факт не проверял. Его пост — это комментарий, а не первоисточник; всё фактическое выше опирается на доку
apple/container, READMEapple/containerization, сессии WWDC 2025/2026 и трекер issue, а не на твит. - Мелочь по доке. Внутри документации есть нестыковка по точному пути монтирования home (
/home/<you>против/Users/<username>) — на сам факт автомаппинга не влияет, но если будешь скриптовать пути, проверь на своей версии.