Running containers on macOS

There is no such thing as a macOS container. Every container you run on a Mac is a Linux container, running inside a Linux VM that something started on your behalf. Once that clicks, most of the confusing behaviour stops being confusing.

Why the VM exists

Containers are a Linux kernel feature — namespaces and cgroups. macOS has neither, so there is nothing for a container to be isolated by. The only way to run one is to bring a Linux kernel along.

# Docker Desktop, colima, OrbStack — all of them are doing this underneath
limactl shell default uname -a

What this explains

Three things that otherwise seem arbitrary:

  1. Bind mounts are slow. Every file read crosses a filesystem boundary between macOS and the VM. Large node_modules trees feel it immediately.
  2. localhost is doing work. The VM forwards ports to your host. It looks seamless, but there's a proxy in the path.
  3. Architecture matters. On Apple Silicon the VM is arm64. Pulling an amd64 image means emulation, and emulation is slow.

Set the platform explicitly when an image only ships one architecture:

docker run --platform linux/amd64 some/legacy-image

A window

If bind mount performance is the thing hurting you, the fix is usually to keep the files inside a volume rather than on the host — the boundary disappears, and so does the cost.