> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ellomas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Container Lifecycle

> How Graft manages Docker container lifecycle.

# 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:

```
/Users/alice/.graft/my-postgres/branches/experiment:/var/lib/postgresql/data
```

On macOS, this goes through the virtio-fs filesystem sharing protocol (Docker Desktop 4.22+ and OrbStack). The database engine sees its data directory at the expected path and runs normally.

## Smart Lifecycle

Graft always captures whether the container was running before any lifecycle operation:

```go theme={null}
wasRunning, _ := client.IsRunning(ctx, s.TargetContainer)
```

If the container was already stopped:

* Stop is skipped
* Start is skipped
* Only the recreate happens

If the container was running:

* Graceful stop (SIGTERM)
* Recreate with new bind mount
* Start

This means running `graft checkout` on an already-stopped container is faster — only the filesystem work and container recreation happen.

## Recreate Flow

```
1. Inspect container → capture wasRunning state
2. Stop container (if running)
3. Remove container
4. Create new container with:
   - Same image
   - Same environment variables
   - Same port bindings
   - Same network mode
   - NEW: bind mount → branch directory
5. Start container (if was running)
```

## 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                 |

The container's identity (name) stays the same, so Docker Compose and other tools that reference the container by name continue to work.

## 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

Graft's downtime is measured in seconds, not minutes. The container is stopped only during the filesystem operation, then immediately restarted.

## 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        |

For development workloads, even the slowest environment is acceptable. Production-grade throughput is not a goal — Graft is a development tool.

## 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.
