Container Lifecycle
Graft manages the container lifecycle by recreating it with a host bind mount pointing at the current branch directory.Bind Mounts
A Docker bind mount maps a host directory directly into the container:Smart Lifecycle
Graft always captures whether the container was running before any lifecycle operation:- Stop is skipped
- Start is skipped
- Only the recreate happens
- Graceful stop (SIGTERM)
- Recreate with new bind mount
- Start
graft checkout on an already-stopped container is faster — only the filesystem work and container recreation happen.
Recreate Flow
Container Metadata Fidelity
When Graft recreates a container, it faithfully reproduces the original configuration:| Setting | Source | Preserved |
|---|---|---|
| Image | Container inspect | Yes |
| Environment variables | Container inspect | Yes |
| Port bindings | Container inspect | Yes (host port may change) |
| Network mode | Container inspect | Yes |
| Exposed ports | Container inspect | Yes |
| Container name | Same as input | Yes |
| Labels | Not yet preserved | On roadmap |
Why Stop the Container?
Database engines cannot be safely snapshotted while running. Postgres uses a Write-Ahead Log (WAL) for durability. Copying data while Postgres is writing would produce:- Half-written WAL segments
- Incomplete
pg_wal/directory - Corrupted heap files
Performance Impact
Bind Mount Performance (macOS)
| Environment | Throughput | Notes |
|---|---|---|
| Linux native | ~1000-3000 MB/s | No VM layer |
| OrbStack | ~400-1000 MB/s | Optimized virtio-fs |
| Docker Desktop 4.22+ | ~200-500 MB/s | virtio-fs |
| Docker Desktop (older) | ~50-150 MB/s | Legacy osxfs |
Snapshot Mode (No Container Management)
Without--bind, Graft leaves the container on its original Docker volume. At commit time, an ephemeral Alpine runner copies data from the Docker volume to the host. The container is never recreated.
This mode has higher commit latency (the Alpine runner must spin up and copy data) but zero container lifecycle risk.