cardinal's pitch is measurable: one small binary, nothing running when you aren't using it. Here's what the project ships and how to verify it on your own host in five minutes.
| Metric | cardinal | Docker | Podman |
|---|---|---|---|
| Binary size | ~5 MB static | ~100+ MB client + daemon | ~50 MB + optional service |
| Idle processes | 0 — nothing runs until invoked | dockerd + containerd + runc | 0 (per-command), optional podman service |
| Idle listening ports | 0 | dockerd socket | 0 (rootless, per-user) |
| Start a container | unshare + overlayfs, one binary | client → daemon → containerd → runc | conmon + runc |
This script sizes the binaries, counts idle processes, and times pulling and starting the same image under cardinal and Docker on the same host:
#!/bin/bash
set -e
echo "== binary size =="
ls -lh $(command -v cardinal) | awk '{print "cardinal:", $5}'
ls -lh $(command -v dockerd) | awk '{print "dockerd: ", $5}'
ls -lh $(command -v podman) | awk '{print "podman: ", $5}'
echo
echo "== idle footprint (nothing running) =="
echo "cardinal processes: $(pgrep -c cardinal || echo 0)"
echo "docker processes: $(pgrep -c dockerd || echo 0) dockerd + $(pgrep -c containerd || echo 0) containerd"
echo
echo "== container start (cold, same image nginx:alpine) =="
/usr/bin/time -f "cardinal: %e s, %M KB peak" cardinal run --rm nginx:alpine echo ok > /dev/null
/usr/bin/time -f "docker: %e s, %M KB peak" docker run --rm nginx:alpine echo ok > /dev/null
echo
echo "== steady-state memory with one container =="
cardinal run -d -n bench-cardinal -p 8081:80 nginx:alpine
docker run -d --name bench-docker -p 8082:80 nginx:alpine
sleep 2
echo "cardinal web RSS: $(ps -o rss= -C unshare | awk '{s+=$1} END {print s/1024 " MB"}')"
echo "docker processes RSS: $(ps -o rss= -C dockerd,containerd | awk '{s+=$1} END {print s/1024 " MB"}')"
cardinal stop bench-cardinal && cardinal rm bench-cardinal
docker stop bench-docker > /dev/null && docker rm bench-docker > /dev/null A static Go binary with no runtime dependencies can live on any VPS, in a cron job, in a rescue system — anywhere a 100 MB+ daemon is overkill. It also means fewer attack-surface code paths and faster cold starts on small disks.
No daemon means no always-on process, no listening socket, no background memory. On a small VPS that's real RAM and real security surface — cardinal exists only while you use it.
See the full feature comparison → Install and measure it yourself