OrbStack vs Colima vs Docker Desktop on Apple Silicon
A team standardising Apple Silicon laptops has to pick one container runtime to document and support, and the usual inputs — a vendor benchmark, a colleague's enthusiasm, whatever the first hire installed — do not answer the question the team actually has: which runtime runs our stack fastest, cheapest and with the fewest support tickets? This page gives a repeatable way to measure that on your own code, with representative numbers from a typical Node and Postgres stack. It sits under choosing and tuning a local container runtime.
All three run the real Docker engine in a Linux VM, so Compose files, images and CLI commands are identical. The differences are in the VM layer: file sharing, memory management, emulation and the surrounding app.
Diagnostic
Measure, do not guess. Run the same benchmark script under each runtime from the project directory, switching with docker context use, on the slowest laptop model the team supports:
#!/usr/bin/env bash
set -euo pipefail
ctx="$(docker context show)"
docker compose down -v >/dev/null 2>&1 || true
docker builder prune -af >/dev/null
t0=$(date +%s); docker compose up -d --build --wait >/dev/null; t1=$(date +%s)
docker compose exec -T web sh -c 'cd /app && rm -rf /tmp/nm && time -p cp -r node_modules /tmp/nm' 2>&1 | awk '/real/{print "copy node_modules: " $2 "s"}'
touch src/index.ts; t2=$(date +%s%N)
until docker compose logs web --since 5s | grep -q 'rebuilt\|compiled'; do sleep 0.1; done
t3=$(date +%s%N)
echo "$ctx cold_up=$((t1-t0))s reload=$(( (t3-t2)/1000000 ))ms"
docker stats --no-stream --format '{{.MemUsage}}' | head -1
Run it three times per runtime and keep the median. Typical results on an M2 Pro with 32 GB, a Next.js frontend with 1,400 files, a Node API and Postgres:
desktop-linux cold_up=94s reload=420ms
colima cold_up=101s reload=460ms
orbstack cold_up=71s reload=180ms
Root cause
The numbers differ because the runtimes implement the host-to-VM boundary differently. Docker Desktop and Colima (with --vm-type vz) both use Apple's Virtualization.framework and virtiofs for bind mounts, which is why they land close together. OrbStack uses its own file-sharing implementation and a lighter VM with dynamic memory, which gives it the lowest latency and idle cost in most measurements. For amd64 images, all three can use Rosetta, so emulation speed is similar once enabled; the difference is only whether it is on by default. The other differences are not performance at all: licensing (Docker Desktop and OrbStack are paid for commercial use above their thresholds, Colima is MIT-licensed), GUI versus CLI configuration, and how much the runtime diverges from Docker Desktop's behaviour in edge cases such as socket paths and host.docker.internal.
Resolution
- Score each runtime on the team's criteria. Weight what actually matters to your organisation — licensing may be a hard filter, and mount speed matters far more for a frontend-heavy monorepo than for a Go service with no bind mounts:
Check edge-case compatibility with the real tooling. Run the integration test suite, a multi-arch
buildxbuild, Testcontainers-based tests, and the Dev Containers extension on each runtime. Record anything that needs a workaround.Pick one runtime to document. Supporting several is possible, but onboarding instructions, the doctor script and troubleshooting guides should assume one. For many teams the outcome is: OrbStack where the licence is acceptable and mount-heavy frontend work dominates; Colima where licensing rules out paid tools or a scriptable, CLI-only setup matters; Docker Desktop where the organisation already pays for it and relies on its enterprise management features.
Encode the choice. Add the runtime's install and start commands to the bootstrap script and its expected context name to the doctor check:
#!/usr/bin/env bash
set -euo pipefail
expected="${EXPECTED_DOCKER_CONTEXT:-orbstack}"
actual="$(docker context show)"
if [ "$actual" != "$expected" ]; then
echo "docker context is '$actual'; the documented runtime is '$expected'"
echo "switch with: docker context use $expected"
exit 1
fi
Expected output
After the decision, every developer's doctor output shows the same context and comparable numbers:
$ make doctor
docker context ........ orbstack (expected orbstack) ok
VM memory ............. 8.0 GiB (need 6.0 GiB) ok
bind mount reload ..... 190 ms (budget 500 ms) ok
amd64 emulation ....... rosetta ok
A reload-latency budget in the doctor check is useful regardless of the runtime chosen: it catches a developer whose VM fell back to a slower mount mode after an update.
Prevention
Re-run the benchmark on major runtime releases. File-sharing implementations change between releases; a ranking from a year ago may no longer hold.
Keep the benchmark script in the repo so the comparison is reproducible by anyone, not a one-off spreadsheet.
Avoid runtime-specific features in Compose files. OrbStack's automatic
*.orb.localdomains and Docker Desktop's Kubernetes toggle are convenient, but anything the stack depends on should work on all three, so a future switch stays a context change. Use the portable .localhost routing approach instead of runtime-provided domains.
Platform caveats
Apple Silicon (ARM64): enable Rosetta for amd64 images in every runtime — Docker Desktop (Settings → General → Use Rosetta), Colima (
--vz-rosetta), OrbStack (on by default). Without it, QEMU emulation makes amd64 containers several times slower and skews any comparison.
macOS (Intel): OrbStack and Colima's
vzmode need macOS 13 or later. On older Intel Macs the comparison is between Docker Desktop and Colima with QEMU, where Docker Desktop's file sharing is usually faster.
WSL2 / Linux: none of the three applies. On Linux, Docker Engine runs natively; on Windows, Docker Desktop with WSL2 or Docker Engine inside a WSL distribution are the realistic options.
Rollback
Each runtime keeps its own images and volumes, so the previous one keeps working while it stays installed. Switching back is one command plus restoring data dumps if volumes are needed:
#!/usr/bin/env bash
set -euo pipefail
docker context use desktop-linux
docker compose up -d --wait
Frequently Asked Questions
Is OrbStack really faster, or is it just a benchmark artefact?
For bind-mount-heavy workloads it is consistently faster in most teams' measurements, because of its file-sharing implementation and lighter VM. For workloads that do not bind-mount source code — compiled services, CI-like test runs — the three are much closer. Measure your own stack with the script above.
Does Colima cost anything?
No. Colima and Lima are open source under the MIT and Apache licences. You still install the Docker CLI, which is also free; only Docker Desktop and OrbStack carry commercial licence terms.
Can we let developers choose their own runtime?
Yes, if the doctor script checks the properties the stack depends on — memory, mount latency, emulation — rather than the runtime's name. Documentation and support are simpler with one default, so pick one to write instructions for.
How do I move images and volumes between runtimes?
Images are simplest to rebuild or pull again. For volumes, dump databases with their native tools under the old runtime and restore under the new one; copying raw volume data between VMs is unreliable.