Zero-Downtime Docker Compose Migrations via Secure Relays
Solving remote volume migration issues without direct host-to-host SSH trust configurations.
Moving a docker-compose service from one machine to another sounds trivial until you do it with real data. Volumes must be transferred intact, ports checked, databases quiesced, environment configs carried over — and every manual step is downtime plus a chance to lose data.
Node Commander, the infrastructure layer of BuildOS, automates this as a migration engine. Here is how it works and why the relay design matters.
The naive approach and its two failure modes
The obvious method is direct host-to-host: SSH into node A, rsync volumes to node B, bring the stack up. Two problems:
- Trust configuration. Direct transfers require node A to hold credentials for node B. Across a fleet, that becomes a mesh of SSH trust relationships to provision, rotate, and audit — exactly the kind of standing access you do not want between production machines.
- No verification discipline. Manual migrations skip checks under time pressure. Was there enough disk on the target? Is the port free? Did the database finish flushing before the copy started? Each skipped check is an outage waiting.
Relay-based transfer
Node Commander already maintains secure SSH connections (via Paramiko) to every node it manages — that is its normal, agentless operating mode. Migrations reuse those connections: the relay system acts as the transfer bridge between source and target, so nodes never need to trust each other directly.
No new keys, no host-to-host trust mesh, no software installed on either machine. The same connection that streams metrics and terminal sessions carries the migration.
The migration sequence
The engine wraps every migration in a strict sequence:
- Preflight checks — disk space on the target, volume sizes, port availability. Fail fast, before anything moves.
- Safe volume handling — database volumes are quiesced and synced so nothing is copied mid-write.
- Transfer — an rsync-based copy of volumes, compose files, and environment configuration through the relay.
- Verification — the stack is started on the target, and container startup status is validated.
- Teardown — only after the target is confirmed healthy does the original stack come down.
The ordering is the whole point. The source keeps serving traffic through steps 1–4; the cutover window shrinks to the moment between "target verified" and "source stopped." That is what near-zero downtime means in practice: not magic, just refusing to tear anything down before its replacement is proven alive.
Watching it happen
Because Node Commander streams container logs and system metrics (CPU, RAM, disk, IO) over WebSockets to the dashboard, the whole migration is observable in real time — including the moment the new stack's containers report healthy.
The broader pattern
This is the same philosophy that runs through all of BuildOS: automation is only trustworthy when it is wrapped in deterministic checks. An agent — human or AI — that can execute migrations is only useful if the system around it makes the unsafe path harder than the safe one.