Deterministic Docker Infrastructure for macOS
Colima • QEMU • LaunchDaemon • Terminal-first • Zero drift
Colima Pulse is a hardened, reproducible way to bring up Docker on macOS using:
- Colima (VM wrapper)
- QEMU (forced; never VZ)
- system
launchdLaunchDaemon supervision (boot domain; no GUI session required) - deterministic health gates (QEMU mode, sockets, Docker API readiness)
- optional container “installers” for smoke-testing (e.g.,
hello-world)
This is for machines where Docker should behave like infrastructure, not “whatever happens when I open Terminal”.
- ALWAYS QEMU (never VZ)
- Docker runtime
- system LaunchDaemon supervising
colima start --foreground - must run as
HOMEBREW_USER(viasu - USER -c ...) - deterministic startup gates
- no-drift workflow (scripted, inspectable, reproducible)
Colima Pulse splits configuration into two categories:
.env is for machine settings that should be safe to keep around:
HOMEBREW_USER(required)- Colima profile and resource limits (
COLIMA_*) - logging and launchd labels (
LABEL,LOG_PATH) - prune preferences (
PRUNE_*) - health gate timeouts (
WAIT_*) - backup destination base path (used only when you explicitly run
--full-reset)
Think: “how this machine should run every day.”
Anything that deletes or rewrites state is intentionally opt-in at runtime:
--full-reset(destructive reprovision)--backup=move|prompt|false(how to handle existing state before deletion)--confirm-token=WORD(interactive safety)--force-yes(required for destructive non-interactive runs)
Think: “I am choosing to do something dangerous right now.”
You will see defaults like this inside the script:
# Enforce runtime model: danger switches are NOT allowed to be driven by .env
FULL_RESET="false"
FORCE_YES="false"
RESET_REQUIRE_CONFIRM="true"
RESET_CONFIRM_TOKEN="DESTROY"
RESET_BACKUP_MODE="move" # move|prompt|falseThis is deliberate:
- It prevents a cloned repo (or a copied
.env) from accidentally becoming destructive. - It ensures restart-only is always the default unless the operator explicitly passes flags.
- It keeps
.env.exampletruly safe for public sharing. - It makes “danger” an explicit, auditable command-line decision (great for runbooks and CI).
Precedence rule: CLI flags override these defaults for the current run.
From cold boot to Docker-ready, Colima Pulse follows this lifecycle:
flowchart TD
A["0) Pre-flight audits/guards<br/>• env resolved<br/>• brew prefix + binaries<br/>• profile/paths validated"] -->
B["1) launchd hygiene<br/>• remove conflicting jobs<br/>• ensure our job is clean"]
B --> C["2) process hygiene<br/>• TERM→KILL: colima/lima<br/>• QEMU cleanup"]
C --> D{"3) state decision<br/>restart-only vs full-reset"}
D -->|restart-only| E["4) provisioning start<br/>• one-time colima start<br/>• enforce runtime=docker<br/>• enforce vm=qemu"]
D -->|full-reset| E
E --> F["5) health gates<br/>• wait socket<br/>• verify QEMU<br/>• wait Docker API<br/>• stability window"]
F --> G["6) launchd supervision<br/>• install LaunchDaemon<br/>• colima start --foreground<br/>• keepalive"]
G --> H["7) optional: container installs<br/>• hello-world smoke test"]
ASCII version (terminal-friendly)
┌───────────────────────────────────────────────────────────────────────┐
│ Colima Pulse lifecycle │
└───────────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────┐
│ 0) Pre-flight audits/guards │
│ - env resolved │
│ - brew prefix + binaries │
│ - profile/paths validated │
└───────────────┬──────────────┘
│
▼
┌──────────────────────────────┐
│ 1) launchd hygiene │
│ - remove conflicting jobs │
│ - ensure our job is clean │
└───────────────┬──────────────┘
│
▼
┌──────────────────────────────┐
│ 2) process hygiene │
│ - TERM→KILL: colima/lima │
│ - QEMU cleanup │
└───────────────┬──────────────┘
│
▼
┌──────────────────────────────┐
│ 3) state decision │
│ - restart-only (default) │
│ - full-reset (destructive) │
│ + optional backup modes │
└───────────────┬──────────────┘
│
▼
┌──────────────────────────────┐
│ 4) provisioning start │
│ - one-time colima start │
│ - enforce: runtime=docker │
│ - enforce: vm=qemu │
└───────────────┬──────────────┘
│
▼
┌──────────────────────────────┐
│ 5) health gates │
│ - wait socket │
│ - verify QEMU │
│ - wait Docker API │
│ - stability window │
└───────────────┬──────────────┘
│
▼
┌──────────────────────────────┐
│ 6) launchd supervision │
│ - install LaunchDaemon │
│ - run: colima --foreground │
│ - keepalive │
└───────────────┬──────────────┘
│
▼
┌──────────────────────────────┐
│ 7) optional: containers │
│ - hello-world smoke test │
└──────────────────────────────┘
On Apple Silicon, macOS Virtualization.framework (“VZ”) can be fast for interactive dev, but Colima Pulse optimizes for boot/session determinism, not peak performance.
Colima Pulse chooses:
- ✅ QEMU + system LaunchDaemon supervision (consistent “no GUI session required” behavior)
- ❌ not VZ (even if faster), because determinism > speed
FileVault encrypts the startup disk at rest. On macOS, after a reboot the disk must be unlocked before user home directories (/Users/...) are available.
What this means for Colima Pulse:
- Colima Pulse can run without a logged-in user, but it still relies on the target user’s home directory (Colima state under
~/.colima, configs/log paths). - If FileVault is enabled and the Mac has just rebooted, LaunchDaemons may start, but they cannot fully bring Colima up until the disk is unlocked at least once.
- After the first unlock following boot, Colima Pulse can run without a user session (logged out is fine) and keep containers alive across logouts.
- FileVault ON + normal reboot: containers are not guaranteed to start until someone unlocks the disk once.
- FileVault OFF: containers can start fully unattended after reboot (subject to power/network).
- This is not “QEMU vs VZ”. It’s boot-time disk unlock determinism.
Pick one:
- Disable FileVault on the host running Colima Pulse (maximum unattended determinism)
- Keep FileVault enabled, but accept: a human must unlock the disk after reboot
- Use enterprise-managed “authorized restart / management tooling” (managed environments)
colima-pulse.sh— canonical bootstrap/provision/supervise script.env.example— safe template (copy to.env)containers/— local installer drop-zone + safe examples/docs (containers/README.md)
- macOS (Intel or Apple Silicon)
- Homebrew installed
- Apple Silicon:
/opt/homebrew - Intel:
/usr/local
- Apple Silicon:
- Admin rights (system LaunchDaemon install)
Colima Pulse expects these tools to exist (via Homebrew), and will install missing ones automatically:
colimadockerqemu
- Make the script executable (first time only)
- Run it — it will detect Homebrew prefix, check dependencies, and install anything missing
chmod +x ./colima-pulse.sh
./colima-pulse.shIf you prefer installing prerequisites yourself:
brew install colima docker qemuNote: QEMU is mandatory for Colima Pulse because the runtime model is QEMU-only (never VZ).
Copy and edit:
cp .env.example .env
$EDITOR .envMinimum required:
HOMEBREW_USER
Common tuning:
COLIMA_PROFILE,COLIMA_CPUS,COLIMA_MEMORY,COLIMA_DISKLABEL,LOG_PATHBACKUP_DIR_BASE(used only when you explicitly run--full-reset)PRUNE_DOCKER_AFTER_START,PRUNE_MODEWAIT_SOCKET_MAX,WAIT_DOCKER_API_MAX,WAIT_QEMU_MAX,WAIT_STABLE_REQUIRED
Prefer
./colima-pulse.sh ...(notzsh ./...) to avoid extra shells and keep TTY/stdout behavior predictable.
./colima-pulse.sh --helpKeeps existing Colima state directories.
./colima-pulse.shReprovisions Colima by deleting/rebuilding state (with safety confirmation).
./colima-pulse.sh --full-reset--backup=move is the default (recommended).
./colima-pulse.sh --full-reset --backup=move
./colima-pulse.sh --full-reset --backup=prompt
./colima-pulse.sh --full-reset --backup=falseDefault token is DESTROY.
./colima-pulse.sh --full-reset --confirm-token=DESTROY--force-yes exists to allow --full-reset when there is no TTY.
It does not mean “skip typed confirmation” in an interactive Terminal.
./colima-pulse.sh --full-reset --force-yesIf your --help output includes --no-confirm, you can use:
./colima-pulse.sh --full-reset --no-confirm
# or (for non-interactive + no-confirm)
./colima-pulse.sh --full-reset --force-yes --no-confirmColima Pulse uses a system LaunchDaemon (system domain) to supervise:
su - $HOMEBREW_USER -c "… colima start --foreground …"
Why this model:
- LaunchAgents require user login (not acceptable for sessionless Docker)
- LaunchDaemons can start at boot, but must drop privileges to the Homebrew user so ownership, paths, and Colima state remain correct
Useful commands:
sudo launchctl print system | grep -i colima
sudo launchctl print system/<LABEL>
sudo launchctl kickstart -k system/<LABEL>
sudo launchctl bootout system/<LABEL>A minimal example container installer lives here:
containers/hello-world/
Purpose: ✅ validate end-to-end readiness:
- Colima up
- Docker socket ready
- Docker API responding
- pull/run works
The containers/ folder is local-by-default because real installers may include secrets.
- The repo commits only documentation + sanitized examples/templates
- Real installers remain local and should be git-ignored
Authoritative policy:
containers/README.md
Docker API readiness:
colima status
docker context ls
docker infoNot using QEMU:
- check for profile overrides
- check for competing system services
Works after login but not after reboot:
- read FileVault and unattended reboots above
MIT — see LICENSE
Most macOS Docker setups are “good enough” until the day you actually need them to behave like infrastructure:
- the machine reboots while you’re not there
- the desktop session isn’t logged in
- a daemon fights another daemon
- Docker looks “up” but the API isn’t ready
- something silently flips modes and your boot semantics change
Colima Pulse is the antidote.
It’s not trying to be clever.
It’s trying to be boringly correct.
If you want a Mac that boots and quietly does its job —
this is for you.