TL;DR
- "Docker" is four things: a desktop app, an engine, a build tool, and the OCI standard. Most alternatives replace one layer, not all of them.
- Podman if you need free at any company size and want rootless, daemonless containers.
- OrbStack if you're on a Mac and want speed (paid for commercial use).
- Colima if you want the lightest free Mac setup with no GUI.
- Rancher Desktop if you deploy to Kubernetes. Finch/nerdctl if you want containerd everywhere.
- Buildah/Kaniko for building images in CI without a privileged daemon.
- And sometimes the fix is a single binary instead of a container stack. Local Supabase is the textbook case.
Why everyone's shopping for alternatives
Let's be honest about the actual pain, because each tool below fixes a different one:
- Licensing. Docker Desktop is paid for commercial use above ~250 employees or $10M revenue. The engine is free; the desktop app isn't.
- RAM and startup on macOS/Windows. It's a Linux VM. 1–2 GB idle and a slow cold start is the norm.
-
Root daemon.
dockerdruns as root on every dev machine. That's a big surface. - Heavy local stacks. Some projects need a dozen containers just to run a backend locally.
Figure out which of these is your problem before picking a replacement.
The stack, layer by layer
Every "Docker alternative" swaps out one row here:
| Layer | Docker | Alternatives |
|---|---|---|
| Desktop app (VM + GUI) | Docker Desktop | OrbStack, Colima, Rancher Desktop, Lima, Finch |
| Engine / CLI |
dockerd + docker
|
Podman, nerdctl + containerd |
| Image builder |
docker build / BuildKit |
Buildah, Kaniko, nerdctl build
|
| Orchestration | Compose, Swarm | Podman Compose, k3s, kind |
| The workload | A container | A single binary |
Your Dockerfiles and images work everywhere because it's all OCI. Only the tooling changes.
Podman: alias it and move on
Daemonless, rootless, OCI-compatible. The closest thing to a drop-in engine replacement.
# macOS
brew install podman
podman machine init && podman machine start
# Fedora / RHEL
sudo dnf install podman
# Ubuntu / Debian
sudo apt install podman
# Existing scripts keep working
alias docker=podman
Same commands you already know:
podman pull nginx:alpine
podman run -d -p 8080:80 --name web nginx:alpine
podman ps
podman logs web
podman stop web && podman rm web
No daemon means each container is a child process owned by you. A container escape lands in your user account, not root.
Podman also has native pods and can spit out Kubernetes YAML from a running one:
podman pod create --name app -p 3000:3000
podman run -d --pod app --name api node:20 node server.js
podman run -d --pod app --name cache redis:7
podman generate kube app > app.yaml
podman compose handles most docker-compose.yml files. Expect the occasional edge case with exotic Compose features.
OrbStack: the fast Mac option
macOS-only. Own VM layer, Docker-compatible engine, so docker and docker compose work as-is.
brew install orbstack
docker run -it --rm alpine sh # that's it
You get ~1s startup, much lower idle memory, zero-config file sharing and port forwarding, lightweight Linux VMs (orb create ubuntu), and optional Kubernetes.
Catch: free for personal use, paid for commercial. Cheaper than Docker Business, but not open source.
Colima / Lima: no GUI, no license, no drama
Lima runs Linux VMs on macOS with file sharing and port forwarding handled. Colima wraps it and gives you a container runtime in one command.
brew install colima docker
colima start # dockerd in a Lima VM
colima start --runtime containerd # or containerd + nerdctl
colima start --cpu 4 --memory 8 --disk 60
colima start --kubernetes
After that, the plain docker CLI just points at Colima's socket. Want more control? Use Lima directly and write your own VM template — it's also what Rancher Desktop and Finch sit on.
Rancher Desktop: containers + local k8s
From SUSE. Container runtime, GUI, and a k3s cluster in one install. Switch runtime between containerd and dockerd in settings.
brew install --cask rancher
nerdctl run -d -p 8080:80 nginx # containerd mode
docker run -d -p 8080:80 nginx # dockerd mode
kubectl get nodes # already there
Heavier than Colima or OrbStack because Kubernetes always ships with it. Worth it if prod is k8s and you want local parity for free.
Finch / nerdctl: go containerd-native
containerd is what's under Docker, Kubernetes, and basically every cloud. nerdctl is a Docker-compatible CLI that talks to it directly. Finch (from AWS) bundles Lima + containerd + nerdctl + BuildKit.
brew install --cask finch
finch vm init && finch vm start
finch run -d -p 8080:80 nginx
finch compose up
No Docker engine in the picture at all — just the runtime everything already standardizes on.
Buildah / Kaniko: your CI doesn't need a daemon
If the pain is in CI rather than on laptops, skip the engine entirely.
Buildah builds OCI images from a Dockerfile with no daemon:
buildah bud -t myapp:latest .
buildah push myapp:latest docker://registry.example.com/myapp:latest
Kaniko builds inside a Kubernetes pod or CI job with no privileged access:
- name: Build with Kaniko
image: gcr.io/kaniko-project/executor:latest
args:
- --dockerfile=Dockerfile
- --context=.
- --destination=registry.example.com/myapp:${CI_COMMIT_SHA}
Both let you delete Docker-in-Docker from your pipeline.
Apple's native container
Since macOS 15.4, Apple ships a native container framework — one lightweight VM per container. Ecosystem is thin right now, but if you're on Apple Silicon it's worth a look.
container system start
container run -it alpine sh
Experimental today. Might be the macOS default in a couple of years.
The alternative nobody lists: no container
Everything above assumes the thing you're running should be a container. For plenty of local dev, that's true. But some workloads are only containerized out of convenience, and the container stack is the overhead.
Local Supabase is the clearest example. supabase start pulls a 12-container stack (Postgres, PostgREST, GoTrue, Storage, Realtime, ...) at 2+ GB of images, just so your app can hit a database on localhost. On a constrained laptop, a locked-down corporate machine, or inside a browser, that's somewhere between painful and impossible.
Tinbase flips it: the Supabase wire protocols (PostgREST, GoTrue, Storage, Realtime) reimplemented in a single process, backed by embedded Postgres 17. No Docker, no VM:
npx tinbase start
Your supabase-js code doesn't change because the API surface is identical:
import { createClient } from '@supabase/supabase-js'
// Tinbase locally, hosted Supabase in prod — same code
const supabase = createClient(
process.env.SUPABASE_URL, // e.g. http://localhost:54321
process.env.SUPABASE_ANON_KEY
)
const { data, error } = await supabase
.from('todos')
.select('*')
.order('created_at', { ascending: false })
It reads the same supabase/migrations/*.sql files as the Supabase CLI, so when you're ready to ship you push the same migrations to hosted Supabase. RLS, auth.uid(), triggers, FKs — all real Postgres behavior, because it's real Postgres.
Caveats, because they matter: it's MIT-licensed and open source, it's alpha (local dev, prototypes, embedded — not prod), and it also has WASM and in-memory engines that run the whole backend in a browser tab.
The bigger takeaway: before you swap one VM manager for another, ask whether the workload needs a container at all. Embedded databases (SQLite, PGlite, embedded Postgres), single-binary services, and in-process runtimes often delete the problem instead of moving it.
Pick one
| Situation | Use |
|---|---|
| Over the Docker Desktop license line, need free at any size | Podman (+ Podman Desktop for GUI) |
| Solo Mac dev, want speed | OrbStack |
| Lightest free Mac setup, no GUI | Colima |
| Deploy to Kubernetes | Rancher Desktop |
| containerd everywhere | Finch / nerdctl |
| Image builds in CI without privileged Docker | Buildah or Kaniko |
| Local Supabase and the stack is the problem | Tinbase |
Things that will bite you when switching
-
Socket path. Testcontainers, VS Code Dev Containers, and some CLIs assume
/var/run/docker.sock. SetDOCKER_HOSTto the new socket (Colima and Podman print it on start). -
Volume mount perf is different. If a mounted
node_modulessuddenly crawls, exclude it or use a named volume. -
Compose edge cases. Test
depends_onconditions andhealthcheckblocks before assuming parity on Podman/nerdctl. - One tool per team. Five engineers on five setups costs more than any of these tools save. Agree on a default and write it down.
Wrapping up
The ecosystem is better because Docker stopped being the only option. Podman covers licensing and security, OrbStack and Colima cover Mac performance, Rancher Desktop and Finch cover k8s and containerd, Buildah and Kaniko cover CI, and for workloads that were only ever containerized out of habit, a single npx command can replace the whole stack.
What did you switch to — or what did you realize never needed a container in the first place? Drop it in the comments.
Top comments (1)