Container Machines: A Persistent Linux Environment on Mac

Apple’s container tool reached 1.0 during WWDC week, and the headline feature answers a gap Mac developers have worked around for years: container machine, a persistent Linux environment that behaves like part of macOS.2 The WWDC session introducing it compresses the pitch into one sentence: “A Container machine is fast and lightweight, like a container, and persistent like a virtual machine.”1 Your repositories and dotfiles are available on both sides, the login user matches your Mac account, and the machine keeps its filesystem between sessions, so the Linux toolchain you set up on Tuesday is still there on Friday.3

Watch on Apple Developer ↗

Session 389, “Discover container machines.”

TL;DR

  • container machine ships in container 1.0.0, released on GitHub during WWDC week. It provides “long-lived Linux environments with tight host integration” on top of the Containerization framework Apple open-sourced at WWDC 2025.2
  • Where containers are “modeled after an application,” a container machine is “modeled after a Linux environment”: it runs the image’s own init system, persists filesystem changes, and is created from standard OCI images.3
  • Host integration is the differentiator. The Linux login user matches your Mac account with passwordless sudo and your home directory is mounted inside the machine,4 and an interactive shell drops you into the same working directory you came from on macOS.1
  • The full subcommand set is create, run, list, inspect, set, set-default, logs, stop, and delete, with m as the short alias.4
  • The 1.0 release also makes one breaking change worth knowing before you upgrade: a TOML configuration file at ~/.config/container/config.toml replaces the old UserDefaults-backed system properties, and the container system property subcommands are gone.2

A Linux environment, not an application sandbox

Apple’s documentation draws the line precisely: “Containers are typically modeled after an application. A container machine is modeled after a Linux environment.”3 The distinction shows up in three behaviors. A container machine runs the image’s own init system, such as systemd or openrc, so you can register long-running services and test your application under a real process supervisor: systemctl start postgresql works the way it does on a Linux box.3 It persists modifications, so tools you install accumulate over time instead of vanishing with the process.1 And it boots from the same OCI images containers use, so an image you build with container build doubles as the starting point for a machine.1

The pull request that landed the feature states the motivation plainly: container runs each workload in an ephemeral VM, so before 1.0 there was no built-in way to keep a persistent Linux environment you could log into and work in.4 Underneath, each container machine still gets the Containerization treatment: its own lightweight virtual machine with VM-based isolation and the sub-second start times the framework was built around.1

The session frames the design goals in workflow terms: switching between macOS and Linux should be easy, environments should be quick to create, and “quick creation allows multiple projects to have their own, dedicated environment, without the worry of conflicting dependencies or toolchains.”1 One machine per target distribution is an intended pattern, and each machine sees the same home directory and dotfiles from your Mac.3

The loop: edit on the Mac, build inside Linux

The session demo is a Vapor web server, and the workflow it walks through is the whole point.1 The project is edited in Xcode on macOS. The build and run happen inside a container machine with the Swift toolchain installed. Safari on the Mac loads the running server by IP address and port. When the presenter re-exports an app icon from Icon Composer on the Mac and overwrites the file, a browser refresh shows the new asset with no copy step, because the machine and the Mac share the same files.1

Apple’s docs generalize the pattern: your repo lives in $HOME on macOS and is mounted inside the machine, so macOS-native tooling (profilers, browsers, GUI debuggers) sees the same files the Linux environment sees. As the documentation puts it, there is no copy step between “I built it” and “I am inspecting it.”3

The host integration runs deeper than a shared mount. The machine automatically creates a Linux user matching your Mac username, grants it passwordless sudo, and mirrors your current working directory, so whoami and pwd answer the same inside and outside.1 The one command that changes its answer is uname: Darwin on the Mac, Linux in the machine.1

One piece of first-day friction is worth knowing before you hit it: a container machine has an isolated network, and the session is explicit that a server inside it must listen on the external interface before a browser on the Mac can reach it.1 The demo handles it the way you will: container machine list displays each machine’s IP address alongside its name and resources, the server config binds to that address, and Safari reaches the app at the machine’s IP and port.1 Plan for the IP-address step in any workflow that serves traffic out of the machine.

The commands

The quickstart is four lines:3

container machine create alpine:latest --name dev
container machine run -n dev whoami       # your host username, not root
container machine run -n dev pwd          # your Mac home directory, mounted in
container machine run -n dev              # interactive shell

container machine run does double duty: with a command it executes once and exits, without one it opens an interactive shell, and if the machine is stopped it boots it first.3 A default machine removes the -n flag from every call:

container machine set-default dev
container machine run                     # operates on dev

Management is the familiar verbs: ls, inspect, logs, stop, and rm, where deleting a machine removes its persistent storage too.3 Resources are adjustable after creation with container machine set -n dev cpus=4 memory=8G, taking effect on the next stop and start; memory defaults to half of host memory, and the home mount can be rw (the default), ro, or none.3 Every command also accepts m as the alias, so m run and m ls work.4

Bring your own machine image

Any Linux image that includes /sbin/init works as a container machine.3 Apple’s docs ship a worked Dockerfile that turns ubuntu:24.04 into a machine image with systemd, OpenSSH, and common command-line tools, then masks the systemd units that make no sense inside a lightweight VM.3 You build it with container build and pass the tag to container machine create.

Provisioning has an escape hatch. By default, container runs a built-in setup script on first boot to create the matching user. An executable at /etc/machine/create-user.sh in the image replaces that script; it runs once, as root, on first boot, with CONTAINER_USER, CONTAINER_UID, CONTAINER_GID, CONTAINER_HOME, and CONTAINER_MACHINE_ID set, so an organization can encode its own user setup into a shared base image.3

The rest of 1.0, including the breaking change

The machine feature headlines the release, but 1.0 carries changes that affect existing users.2

The breaking one is configuration. A TOML file replaces the UserDefaults-backed system properties, and the container system property get and set subcommands are removed.2 The service reads ~/.config/container/config.toml at startup with first-match-wins precedence (your user file, then an optional file shipped with the package install, then hardcoded defaults), and changes require a service restart to take effect.6

The quality-of-life additions: a container cp command for copying files, a --stop-signal option on container run, and cleaned-up structured output (JSON, YAML, TOML) for the ls and inspect commands across containers, images, networks, and volumes.2 Networking gets a correctness fix that uses XPC connections as leases to stop IP address leaks.2 Compatibility with the version 0 XPC APIs is removed, with a versioned API promised in a later release.2

The requirements hold steady from the 0.x line: a Mac with Apple silicon, running macOS 26. The maintainers state they typically will not address issues that cannot be reproduced on macOS 26.5

Why agent workflows should care

A reading from where I sit, not an Apple claim: a container machine is the shape of environment coding agents want. Agents running on a Mac need somewhere to execute builds, run servers, and install dependencies without touching the host: fast to create, isolated by a real VM boundary, persistent enough that a toolchain installed in one session survives to the next. Until now the Mac answers were Docker Desktop-style VMs (heavyweight, one big shared environment) or ephemeral containers (isolated but forgetful). A machine per project, created from a versioned OCI image, with the repo mounted in and passwordless sudo inside, matches how agent sandboxes already work on Linux hosts.

The same property serves plain cross-platform work. Server-side Swift is the obvious beneficiary: the session demo is Vapor, and the Foundation Models framework goes open source this summer with Linux support, so the test environment for “does my Swift code run on Ubuntu” is now one container machine create away. The comparison that will occur to anyone who has used Windows is WSL, and the direction of integration is the same: a real Linux kernel a shell away, with your files visible on both sides. Apple’s version arrives with an image-based workflow already attached.

FAQ

What is a container machine?

A container machine is a persistent Linux environment on macOS, shipped as a feature of Apple’s open-source container tool starting in version 1.0.0.2 It runs in its own lightweight virtual machine via the Containerization framework, boots from standard OCI images, runs the image’s init system, and persists filesystem changes between sessions.1 Host integrations mount your home directory inside, match the Linux user to your Mac account with passwordless sudo, and keep your working directory consistent across the boundary.4

How is it different from a regular container?

Apple’s docs put it in one line: containers are “modeled after an application,” a container machine is “modeled after a Linux environment.”3 A regular container run workload is ephemeral and process-centric. A machine is stateful, runs systemd or openrc, and is meant to be revisited over time, like a VM with container creation speed.1

What does it require?

A Mac with Apple silicon running macOS 26, the same requirements as the container tool generally.5 The tool is open source on GitHub, written in Swift.5

Does upgrading to 1.0 break anything?

One thing: system configuration moves from UserDefaults-backed properties to a TOML file at ~/.config/container/config.toml, and the container system property get/set subcommands are removed.2 The 1.0 release notes link a tutorial for the migration.2 The version 0 XPC API compatibility is also removed, which matters if you built clients against the API.2


Container machines slot into the same story this WWDC kept telling: the Mac as a serious home for cross-platform and agentic development. Running Agentic AI on the Mac with MLX covers the model-serving half of that story, and What’s New in Swift (2026) covers the language work that makes Swift-on-Linux a first-class target. The full series hub is the Apple Ecosystem Series.

References


  1. Apple, WWDC 2026 session 389, Discover container machines. Official transcript. Source for the definition (“A Container machine is fast and lightweight, like a container, and persistent like a virtual machine”), the Containerization recap (Swift framework for Linux containers on macOS, VM-based isolation, sub-second start times, open-sourced at WWDC 2025 along with the container tool), the design principles (including “quick creation allows multiple projects to have their own, dedicated environment, without the worry of conflicting dependencies or toolchains”), the OCI image reuse, statefulness, automatic user mapping and working-directory mirroring, the uname Darwin/Linux demo, and the Vapor workflow demo (edit in Xcode on macOS, build and run inside the machine, load from Safari by machine IP, Icon Composer asset update visible without a copy step). 

  2. Apple, container 1.0.0 release notes, GitHub. Source for the 1.0.0 release, the “long-lived Linux environments with tight host integration” description, the breaking TOML configuration change (replacing UserDefaults-backed system properties and removing the container system property get and set subcommands, with a linked migration tutorial), the container cp command, the --stop-signal option, the structured output cleanup for ls and inspect across containers, images, networks, and volumes, the XPC-connection-as-lease fix for IP address leaks, and the removal of version 0 XPC API compatibility with a versioned API promised in a subsequent release. 

  3. Apple, Container machine documentation, apple/container repository. Source for the application-versus-environment framing (“Containers are typically modeled after an application. A container machine is modeled after a Linux environment”), the init-system behavior including the systemctl start postgresql example, the edit-on-Mac/build-inside workflow and the no-copy-step framing, the one-machine-per-distro pattern with shared $HOME and dotfiles, the quickstart commands, run booting a stopped machine, set-default, the management verbs with rm deleting persistent storage, set for cpus/memory taking effect after stop and start, the half-of-host-memory default, the rw/ro/none home-mount modes, the /sbin/init requirement for machine images, the Ubuntu 24.04 Dockerfile example, and the /etc/machine/create-user.sh first-boot hook with its CONTAINER_USER, CONTAINER_UID, CONTAINER_GID, CONTAINER_HOME, and CONTAINER_MACHINE_ID variables. 

  4. Apple, pull request #1662: Add container machine for managing persistent Linux environments, apple/container repository, merged June 8, 2026. Source for the motivation (each workload runs in an ephemeral VM, with no built-in way to keep a persistent Linux environment to log into), the login user matching the host account with passwordless sudo, the home directory mount, the machine keeping its filesystem and running the image’s own init system such as systemd or openrc, the full subcommand list (create, run, list/ls, inspect, set, set-default, logs, stop, delete/rm), and the m alias. 

  5. Apple, container README, GitHub. Source for the requirements (a Mac with Apple silicon; supported on macOS 26, with maintainers typically not addressing issues that cannot be reproduced on macOS 26) and the description of the tool as written in Swift and optimized for Apple silicon. 

  6. Apple, container configuration tutorial, apple/container repository. Source for the configuration file location at ~/.config/container/config.toml, the first-match-wins precedence (user file, then an optional file shipped with the package install, then hardcoded defaults), and the service reading the file once at startup so changes require a restart. 

Related Posts

What Apple's Swift Team Said in the WWDC26 Lab

Apple's Swift Group Lab at WWDC26 ran without captions. We transcribed it locally. Candid engineer answers on concurrenc…

14 min read

What's New in Swift (2026): The WWDC26 Update

Swift 6.3 and 6.4 from WWDC26: anyAppleOS availability, module selectors, borrow/mutate accessors, the Iterable protocol…

19 min read

Engineering Philosophy: Mark Shuttleworth

Mark Shuttleworth built Ubuntu on one idea -- Linux for human beings, free software for everyone -- grounded in ubuntu: …

25 min read