Container machines are a new feature of the open-source `container` CLI tool and Containerization framework that provide a persistent, lightweight Linux environment on macOS. They combine the speed of containers with the statefulness of virtual machines, featuring automatic user mapping and shared filesystem support for seamless cross-platform development.
โข Developers get a persistent Linux environment that mirrors their macOS username and working directory โ no manual file syncing or SSH key setup required
โข Built on the same OCI image format as containers, so existing container images (like alpine or swift toolchain images) work as starting points immediately
โข Enables native-feeling cross-platform workflows: edit in Xcode on macOS, build and run on Linux, test in Safari โ all within a single terminal session
Demonstrates the key CLI commands for creating and using a container machine, plus a Swift Package Manager server target that binds to the container machine's IP for macOS-reachable testing.
// Container Machine workflow โ run these in Terminal on macOS 26
// Requires: https://github.com/apple/container (open-source CLI tool)
// 1. Create a new container machine named "dev" and set it as default
// container machine create dev --default --image alpine
// 2. Run a quick command inside the machine
// container machine run uname // prints: Linux
// 3. Start an interactive shell โ your macOS username + working directory
// are automatically available inside the machine
// container machine run // launches interactive bash/sh
// 4. List all container machines (name, IP, resources)
// container machine list
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// Swift: Vapor-style server configured to bind to the container
// machine's external IP so Safari on macOS can reach it.
// Package.swift target: .executableTarget(name: "Server", dependencies: [...])
import Foundation
#if canImport(Glibc)
import Glibc
#endif
// Resolve the container machine's IP at launch via environment variable
// Set CONTAINER_HOST_IP when invoking: CONTAINER_HOST_IP=192.168.64.5 swift run
let hostname: String
if let envIP = ProcessInfo.processInfo.environment["CONTAINER_HOST_IP"],
!envIP.isEmpty {
hostname = envIP
} else {
hostname = "127.0.0.1" // fallback for local macOS testing
}
let port = 8080
print("[Server] Binding to \(hostname):\(port)")
// Minimal POSIX TCP listener to illustrate the binding concept
let sock = socket(AF_INET, Int32(SOCK_STREAM.rawValue), 0)
guard sock >= 0 else { fatalError("socket() failed") }
var addr = sockaddr_in()
addr.sin_family = sa_family_t(AF_INET)
addr.sin_port = in_port_t(port).bigEndian
addr.sin_addr = in_addr(s_addr: inet_addr(hostname))
withUnsafePointer(to: &addr) { ptr in
ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { saddr in
let result = bind(sock, saddr, socklen_t(MemoryLayout<sockaddr_in>.size))
if result == 0 {
print("[Server] Bound successfully โ accessible from macOS Safari at http://\(hostname):\(port)")
} else {
print("[Server] bind() failed: \(String(cString: strerror(errno)))")
}
}
}
close(sock)Container machines are managed via the `container` CLI tool (open source), not a Swift API you embed in your app. The Containerization Swift framework underpins the runtime but direct programmatic control of container machines is via the CLI or its open-source Swift package. Persistent state is stored per machine โ destroying a machine is irreversible. Network isolation means you must bind your server to the machine's IP, not localhost, to reach it from macOS Safari.
macOS only; requires Apple Silicon or Intel Mac running macOS 26; not applicable to iOS/iPadOS; each machine runs in its own lightweight VM
More iOS 27 APIs land every week.
Get notified when new capabilities are published โ no noise, just signal.