Docker using too much memory on a Mac
On a Mac, containers run inside a Linux virtual machine, and the VM is what holds the memory. Activity Monitor shows it as com.apple.Virtualization.VirtualMachine, often at several gigabytes, and it rarely shrinks when your containers stop. To get the memory back, stop the VM; to keep it from coming back, give it a lower limit.
See what's using it
Inside the VM, per container:
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}"NAME MEM USAGE / LIMIT shop-web-1 412.3MiB / 7.654GiB shop-postgres-1 96.18MiB / 7.654GiB shop-redis-1 8.52MiB / 7.654GiB
The number after the slash is the size of the VM, the most it can take from your Mac. The containers' numbers are their shares of it.
Outside the VM, search for Virtual in Activity Monitor's Memory tab. If your setup still runs on QEMU, the VM is qemu-system-aarch64 instead. That's the number that counts against your Mac, and it's usually larger than the containers add up to.
Get the memory back
Stopping containers frees memory inside the VM, but the VM tends to keep what it already took from macOS. Stopping the VM gives all of it back:
# the containers of one Compose project, from its folder docker compose down # then the VM itself docker desktop stop # Docker Desktop 4.39 or later, or Quit from the whale menu orb stop # OrbStack colima stop # Colima
OrbStack hands unused memory back to macOS by itself, so its VM shrinks after containers stop. With Docker Desktop and Colima, stopping the VM is the reliable way to get the memory back. Starting it again takes a few seconds.
Give the VM a lower limit
- Docker Desktop: Settings → Resources → Advanced → Memory limit. By default it can take half your Mac's memory. On the same page, Resource Saver pauses the VM when no containers have run for a few minutes; leave it on.
- OrbStack: Settings → System → Memory limit, or
orb config set memory_mib 4096. - Colima:
colima stop, thencolima start --memory 4. The value is in GiB; the default is 2.
4 GB is enough for a web app with a database and a cache. Raise it if containers start getting killed for running out of memory. To keep one service from filling the VM, cap it in compose.yaml:
services:
web:
mem_limit: 512mA cap on a container doesn't make the VM smaller; it only decides which container hits the wall first.