Skip to content

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:

Create a container machine
container machine create alpine:latest --name dev

The machine command has an alias m for brevity:

Using the alias
container m create alpine:latest --name dev

Run it (opens an interactive shell, boots the VM first if it is stopped):

Run the container machine
container machine run -n dev

Now you are inside a Linux shell with your macOS username, home directory, and dotfiles available.

Stop it when done:

Stop the machine
container machine stop dev

Next time you run it, your filesystem is still there.

Containers vs Container Machines

AspectRegular ContainerContainer Machine
PersistenceEphemeralPersistent filesystem
Init systemNoYes (systemd)
User mappingRuns as specified userAuto-maps your Mac username
Home directoryMust mount manuallyAuto-mounted
Use caseRun an app/serviceLinux development environment
Default memory1 GBHalf of system memory
ResizeVia container run --memorycontainer machine set cpus=4 memory=8G

Running systemd Services

Inside a container machine, init systems work normally:

Install and start PostgreSQL inside a container machine
apk add postgresql
rc-update add postgresql default
rc-service postgresql start

The service persists across machine restarts.

Managing Resources

Default memory is half of your system memory. Change it:

Resize a container machine
container machine set cpus=4 memory=8G

VS Code Remote Development

The Apple container repository includes an example for VS Code SSH remote development (examples/container-machine-vscode/). The workflow:

  1. Create a container machine with a Linux image that has systemd and SSHD
  2. Set up SSH config to connect to the machine
  3. 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.

Create a machine from a custom image
container machine create my-custom-image:latest --name work-env

Summary

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