# apple/containerization: a Swift package for running Linux containers on macOS

> Apple's Containerization package puts each Linux container inside its own lightweight VM on Apple silicon, with a second backend for Linux hosts. It is a library for Swift developers, not a Docker replacement you install and forget.

**apple/containerization** — Containerization is a Swift package for running Linux containers on macOS.

- Repository: https://github.com/apple/containerization
- Website: https://apple.github.io/containerization/documentation/
- Stars: 8,948 · Forks: 371
- Language: Swift
- License: Apache-2.0
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/apple-containerization

## What Containerization is for, and who should reach for it

Containerization is a Swift package for running Linux containers on macOS. It is not a command line tool. The README states this explicitly: if you are looking for command line binaries for running containers, they live in the separate apple/container repository. What you get here is an API surface a Swift application links against.

The README lists what those APIs cover: managing OCI images, talking to remote registries, creating and populating ext4 file systems, interacting with the Netlink socket family, building an optimized Linux kernel for fast boot times, spawning lightweight virtual machines, and spawning and interacting with containerized processes. There is also Rosetta 2 support for running linux/amd64 containers on Apple silicon.

That list tells you who this is for. It is for someone writing a container runtime, a build tool, a test harness, or an application that needs to launch Linux processes without asking the user to install Docker. If your goal is to run a container from a shell, this package is the wrong layer.

## One VM per container, and the vminitd process inside it

The design choice that shapes everything else: Containerization executes each Linux container inside its own lightweight virtual machine. That is a different architecture from a shared-kernel container runtime, where containers are processes isolated by kernel namespaces on one host kernel. Here the isolation boundary is the hypervisor.

The README describes what that buys. Clients can create dedicated IP addresses for every container, which removes the need for individual port forwarding. Containers get sub-second start times from an optimized Linux kernel configuration plus a minimal root filesystem with a lightweight init system.

That init system is vminitd, a subproject inside Containerization. It is spawned as the initial process in the VM and exposes a GRPC API over vsock. Through that API the runtime environment is configured and containerized processes are launched. vminitd also supplies I/O, signals and events back to the calling process when a process runs. So the data flow is: your Swift code talks to a VM, the VM boots vminitd, and your process control travels over vsock rather than over a local Unix socket to a daemon.

The package abstracts the VMM behind the VirtualMachineManager and VirtualMachineInstance protocols and ships two implementations. On macOS the shipping path is VZVirtualMachineManager, built directly on Apple's Virtualization framework, with no extra binaries required. On Linux there is CHVirtualMachineManager, one cloud-hypervisor subprocess per VM, controlled over its REST-on-UDS API by a standalone CloudHypervisor Swift package. Block storage there uses virtio-blk, shared directories use virtio-fs with one virtiofsd per share, networking uses TAP, and the guest agent is reached over cloud-hypervisor's hybrid vsock. The README notes that guest-side semantics are unchanged because both paths keep the same vminitd contract.

## Installing the package and running something through cctl

The build requirements are narrow and worth reading before you start. You need a Mac with Apple silicon, macOS 26 and Xcode 26. The README says older versions of macOS are not supported.

First install the recommended version of Xcode and point the active developer directory at it, replacing the placeholder with your actual path:

```bash
sudo xcode-select -s <PATH_TO_XCODE>
```

One detail removes a lot of setup pain. The Linux guest init, vminitd and vmexec, is compiled as a static binary inside a Linux container rather than cross-compiled on your Mac, so no Swift toolchain, Swiftly or Static Linux SDK setup is required on the host.

For a first real use, the README points at the cctl executable as a useful playground for exploring the API. It contains commands that exercise core functionality: manipulating OCI images, logging in to container registries, creating root filesystem blocks, and running simple Linux containers. The relevant sources are ImageCommand.swift, LoginCommand.swift, RootfsCommand.swift and RunCommand.swift under Sources/cctl. The README does not print the exact cctl invocation for each subcommand, so read those files rather than guessing at flags.

A Linux kernel is required for spawning the VMs. The package ships an optimized configuration in the kernel directory with a containerized build environment, and the kernel README covers compiling it. If you prefer a pre-built kernel, the constraint is specific: make sure it has VIRTIO drivers compiled into the kernel, not merely as modules. The README names Kata Containers as a source of a suitable kernel, with downloadable artifacts on its releases page and vmlinux.container in /opt/kata/share/kata-containers/. Containerization tests functionality starting with kernel version 6.14.9.

## The Linux backend asks you to bring your own plumbing

The cloud-hypervisor backend is the clearest limitation in the README, and it is a deliberate one. It requires cloud-hypervisor and virtiofsd on the host, both looked up on PATH by default, with CHVirtualMachineManager.init accepting explicit URLs to override. virtiofsd is resolved lazily, so a VM that uses only block-device mounts can run without it installed at all. Recent stable releases of each are recommended, and the README notes that smoke testing pins specific versions, which means the tested combination is narrower than the range of versions that will probably work.

You also need KVM access: /dev/kvm readable and writable by the calling user. And if the container needs networking, you must pre-stage the TAP, bridge and NAT plumbing yourself. TAPInterface consumes an existing TAP device by name; bringing it up, attaching it to a bridge, and configuring NAT or routing is the caller's responsibility. That is a real amount of host configuration to own compared with the macOS path, where the Virtualization framework handles the equivalent work.

There is a further asymmetry. The integration test suite runs with make linux-integration inside an apple/container Linux VM with nested virt enabled via container run --virtualization. The kata kernel fetched by make fetch-default-kernel does not enable KVM, so the suite uses the in-repo kernel at kernel/vmlinux-arm64, or kernel/vmlinuz-x86_64 on x86_64 hosts, and you build it with make -C kernel first. On Linux the suite runs only the cross-platform scenarios that do not depend on macOS-only types; the README says the full suite remains macOS-only for now. If you are targeting Linux, your coverage of this package is thinner than the project's own.

## Where this is the wrong tool, and what to use instead

The wrong tool for most people reading about containers: if you want a Docker-style workflow on a Mac, this package does not give it to you. The README redirects command line users to apple/container. The distinction matters because the two projects share a name space and a codebase but not an audience. Containerization is the library; apple/container is where the binaries live.

For the comparison people actually search for, containerization versus virtualization, this project sits on an unusual line. Classic containerization shares the host kernel and isolates with namespaces, which is cheap and fast but couples the container to the host kernel. Classic virtualization gives each workload its own kernel, which isolates more but costs a full boot. Containerization does virtualization per container and then works hard to make it cheap: a minimal kernel configuration, a minimal root filesystem, a lightweight init, and sub-second start times per the README. That is the trade it makes, and it is why the kernel configuration and the root filesystem are part of the package rather than an afterthought.

If you do not need the API, the honest alternative is whatever container CLI you already run, including apple/container on macOS. If you need the VM-per-container model on macOS and you are not writing Swift, this package will not help you directly, because the documented surface is a Swift package. Nothing in the README describes bindings for other languages.

## Maintenance, licensing and what an upgrade costs

The repository is not archived and the last push was on 2026-09-21, so it is being worked on. The release list is short and every entry carries a prerelease marker: 0.33.3 from 2026-06-01, 0.26.5 from 2026-02-28 and 0.26.4 from 2026-02-26. The version jump between 0.26.x and 0.33.x, with no stable releases listed, is the practical signal here. Treat the API as moving and pin a version in Package.resolved rather than tracking main.

The licence is Apache-2.0, and the source files carry the standard Apache header. Apache-2.0 is permissive and includes an explicit patent grant, which matters for a project that touches hypervisor and kernel interfaces. This is a description of the licence text, not legal advice; if you are shipping a product, have your own counsel read it alongside the kernel and Kata Containers components you pull in, since those come from other projects with their own terms.

Upgrade cost is dominated by the host requirements rather than the Swift API. macOS 26 and Xcode 26 are hard floors, and the README states older macOS versions are not supported, so an upgrade of this package can force an OS upgrade on your development machines. On the Linux side, upgrading means re-checking the pinned cloud-hypervisor and virtiofsd versions against the smoke-tested set, and re-verifying KVM access and your TAP and bridge configuration. Kernel support starts at 6.14.9 per the README, and a pre-built kernel must have VIRTIO compiled in rather than as modules, so swapping kernels is a build decision, not a config change.

## Conclusion

Adopt it if you are building a Swift application on Apple silicon that needs to start Linux containers itself, or if you need a Linux backend driven by cloud-hypervisor and KVM. Do not adopt it if you just want to run `docker run` on a Mac; the README points command line users to apple/container instead, and the package requires macOS 26, Xcode 26 and a Mac with Apple silicon. Before committing, verify three things: that your target machines run macOS 26, that your kernel has the VIRTIO drivers compiled in rather than built as modules, and, if you use the Linux backend, that /dev/kvm is readable and writable by the calling user and that cloud-hypervisor and virtiofsd are on PATH. The oldest release in the list is 0.33.3, marked prerelease, so pin a version rather than tracking main.

## FAQ

### How do I install apple/containerization?

Install the recommended version of Xcode and set the active developer directory with sudo xcode-select -s <PATH_TO_XCODE>. The package needs a Mac with Apple silicon, macOS 26 and Xcode 26, and the README states older versions of macOS are not supported. The Linux guest init is built inside a Linux container, so no Swift toolchain or Static Linux SDK setup is needed on the host.

### How do I use apple/containerization?

You use it as a Swift package rather than a command line tool. The README points at the cctl executable as a useful playground for exploring the API, with commands for manipulating OCI images, logging in to registries, creating root filesystem blocks and running simple Linux containers. If you want command line binaries for running containers, the README directs you to the separate apple/container repository.

### How does apple/containerization run containers differently from a typical container runtime?

It executes each Linux container inside its own lightweight virtual machine rather than sharing the host kernel. A small init system called vminitd is spawned as the initial process in the VM and provides a GRPC API over vsock for configuring the runtime and launching processes. The README states that clients can create dedicated IP addresses for every container, removing the need for individual port forwarding.

### What kernel does apple/containerization need?

A Linux kernel is required to spawn the lightweight virtual machines. The package ships an optimized configuration in the kernel directory with a containerized build environment, and the README says functionality is tested starting with kernel version 6.14.9. If you use a pre-built kernel, it must have the VIRTIO drivers compiled into the kernel rather than as modules.

### Can I use apple/containerization on Linux?

Yes, through the cloud-hypervisor and KVM backend, which runs one cloud-hypervisor subprocess per VM. It requires cloud-hypervisor and virtiofsd on the host, KVM access with /dev/kvm readable and writable by the calling user, and pre-staged TAP, bridge and NAT plumbing if the container needs networking. The README notes that on Linux the integration suite runs only the cross-platform scenarios, and the full suite remains macOS-only for now.

## Sources

- [apple/containerization on GitHub](https://github.com/apple/containerization)
- [License: Apache-2.0](https://github.com/apple/containerization/blob/main/LICENSE)
- [Project website](https://apple.github.io/containerization/documentation/)
- [README](https://github.com/apple/containerization/blob/main/README.md)
- [Releases](https://github.com/apple/containerization/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/apple-containerization
