What Is a Container Machine? Persistent Linux Dev Environments on Mac with Apple container
Problem
I often need a Linux environment for development — compiling C code, running PostgreSQL, testing systemd services. My options on macOS were:
- UTM / Parallels: full VMs, heavy on resources, slow to boot
- multipass: lighter, but still a full Ubuntu VM
- Docker containers: ephemeral, no init system, changes lost on restart
None of them felt right. Full VMs are too heavy for quick tasks. Regular containers lose state. I wanted something in between: a persistent Linux environment that boots fast and keeps my files.
What Is a Container Machine?
A container machine is a persistent Linux environment built from an OCI image that runs as an Apple container. Unlike regular containers (ephemeral, app-focused), container machines:
- Keep their filesystem across restarts
- Mount your macOS home directory automatically
- Match your host username
- Can run init systems like systemd
Think of it as “a Docker container that acts like a lightweight Linux laptop.”
┌─────────────────────────────────────────────┐│ Regular Container Container Machine ││ ││ Ephemeral Persistent ││ No init system systemd ready ││ Runs as root Your username ││ Dies when process exits Reusable ││ App-focused Dev-focused │└─────────────────────────────────────────────┘Quickstart
Create a container machine:
container machine create alpine:latest --name devThe machine command has an alias m for brevity:
container m create alpine:latest --name devRun it (opens an interactive shell, boots the VM first if it is stopped):
container machine run -n devNow you are inside a Linux shell with your macOS username, home directory, and dotfiles available.
Stop it when done:
container machine stop devNext time you run it, your filesystem is still there.
Containers vs Container Machines
| Aspect | Regular Container | Container Machine |
|---|---|---|
| Persistence | Ephemeral | Persistent filesystem |
| Init system | No | Yes (systemd) |
| User mapping | Runs as specified user | Auto-maps your Mac username |
| Home directory | Must mount manually | Auto-mounted |
| Use case | Run an app/service | Linux development environment |
| Default memory | 1 GB | Half of system memory |
| Resize | Via container run --memory | container machine set cpus=4 memory=8G |
Running systemd Services
Inside a container machine, init systems work normally:
apk add postgresqlrc-update add postgresql defaultrc-service postgresql startThe service persists across machine restarts.
Managing Resources
Default memory is half of your system memory. Change it:
container machine set cpus=4 memory=8GVS Code Remote Development
The Apple container repository includes an example for VS Code SSH remote development (examples/container-machine-vscode/). The workflow:
- Create a container machine with a Linux image that has systemd and SSHD
- Set up SSH config to connect to the machine
- Use VS Code Remote-SSH to open the machine as your dev environment
This gives you a full Linux IDE experience with your macOS desktop.
Custom Images
Any Linux image with /sbin/init works as a container machine. Build custom images with container build. For custom user provisioning, use /etc/machine/create-user.sh inside the image.
container machine create my-custom-image:latest --name work-envSummary
In this post, I explained what a container machine is and how it fills the gap between ephemeral containers and heavy full VMs. The key point is that container machines give you a persistent, init-system-ready Linux environment with your macOS identity — ideal for daily development work.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments