Linux containers that give memory back to your Mac.
A runtime plugin for Apple Container that boots Apple’s own Linux guest with libkrun instead of Virtualization.framework. When the guest frees memory, macOS can reclaim it, and the container keeps running.
How freed memory gets back to macOS
Apple’s stock Container kernel negotiates VIRTIO_BALLOON_F_REPORTING with libkrun. Nothing in apple/container or apple/containerization changes; the plugin uses Apple Container’s public runtime plugin contract.
-
The guest frees pages
A process inside the container exits or releases memory, and the Linux kernel returns those pages to its free lists.
-
The kernel reports them
The virtio-balloon driver batches free pages and reports them to the VMM, without any manual balloon inflation.
-
libkrun releases the backing
libkrun marks the host memory behind those pages with
MADV_FREE. -
macOS reclaims it
Under memory pressure, macOS takes the pages back for other apps while the container keeps running.
How it compares with Apple’s runtime
Network throughput matches or beats Apple’s runtime. File copies and volume writes are faster. Stopping a container takes about 23 ms longer.
Network throughput
| Direction | krun ÷ Apple | Result |
|---|---|---|
| Guest to host, BBR |
|
11–17% faster1.11× median, earlier 1.17× |
| Guest to host, Reno |
|
Same speed1.01× median, earlier 0.97× |
| Host to guest |
|
Same speed1.00× median, earlier 0.98× |
Container lifecycle and file I/O
| Operation | Median time | krun vs Apple |
|---|---|---|
| Start a container | 3% fasterwithin noise | |
| Stop a container | 27% slower+23 ms | |
| Delete a container | 10% faster | |
exec a command |
5% slowerwithin noise | |
| CPU workload | 2% faster | |
copyIn |
15% faster | |
copyOut |
15% faster | |
| Write to a volume | 11% faster |
Works with the container commands you already use
Select the runtime with --runtime container-krun-runtime. Apple Container still manages images, networks, and volumes.
Lifecycle
run,exec, stop, signals, waitInteractive stdio and terminal resize--initSignal forwarding and zombie reapingcontainer logsInit output plus the VM boot log- Container statistics
- Live rootfs export
Networking
- Native vmnet on macOS 26Works with no setup through a managed
krunnetwork - Multiple networksExtra attachments become
eth1,eth2, … - Published TCP and UDP portsThrough Apple’s
SocketForwarder - Published Unix socketsWorks with
--network none - SSH agent forwarding with
--ssh
Storage
- Named and anonymous volumesAttached as virtio-blk devices
- Host directory mountsvirtio-fs, read-write or read-only
copyInandcopyOutcontainer cleanTrims the rootfs and block-backed mounts
Not supported
- Rosetta. Use Apple’s default runtime for x86_64 images.
- Nested virtualization.
Unsupported requests fail with a clear error instead of silently falling back.
Install
Install it next to Apple’s runtime and opt in per container. The project is experimental.
You need
- An Apple Silicon Mac on macOS 26 or later
- Apple Container 1.5.0 or later
- Administrator approval, once, for the network helper
Networking needs a root-owned copy of the VM helper and a sudo rule that lets only you run it. container-krun-runtime-setup installs both and asks for your password for that step only. Pass --no-network to skip it; containers started with --network none still work.
-
Install the package
brew install RobertDeRose/tap/container-krun-runtime -
Register it with container
container-krun-runtime-setup container system stop && container system start -
Run a container
container run --rm \ --runtime container-krun-runtime \ alpine:3.20 echo hello-from-libkrun
Run container-krun-runtime-setup again after brew upgrade changes either package.
-
Install the package
mise use -g packslip:github.com/RobertDeRose/container-krun-runtime -
Register it with container
container-krun-runtime-setup container system stop && container system start -
Run a container
container run --rm \ --runtime container-krun-runtime \ alpine:3.20 echo hello-from-libkrun
mise checks the release’s packslip signature against this repository before installing. To run setup after every mise upgrade, add it as the tool’s postinstall; the README has the snippet.
-
Install build tools
brew install llvm lld xz mise install -
Build, install, and register
scripts/fetch_libkrun.sh mise run native:install container system stop && container system start -
Run a container
container run --rm \ --runtime container-krun-runtime \ alpine:3.20 echo hello-from-libkrun
Needs Xcode with Swift 6.2 or later. The build stages the same package a release ships and runs its setup.