# Docker Image Plan for Repartee

## Date: 2026-03-29

## Base Image Decision

Repartee dynamically links against `libchafa` and `libglib-2.0` at runtime (via ratatui-image).
SQLite and Lua are bundled (vendored), TLS uses rustls (no OpenSSL).

| Base Image | Size | Viability |
|---|---|---|
| `scratch` | ~0 MB | Not viable — needs glibc + libchafa |
| `distroless/static` | ~2 MB | Not viable — no shared libs |
| `alpine` | ~8 MB | Risky — musl, not glibc; chafa may have issues |
| **`debian:trixie-slim`** | ~75 MB | **Best choice** — current stable, chafa 1.14.5, long support |
| `ubuntu:24.04` | ~78 MB | Works but Debian slim is smaller |

**Recommendation**: `debian:trixie-slim` (Debian 13, released Aug 2025).
Runtime package: `libchafa0t64` (renamed for 64-bit time_t transition).

If chafa is made optional (feature flag), `scratch` becomes viable for a ~20MB image.

## Multi-Stage Build Pattern (cargo-chef)

Four stages:
1. **base**: rust image + cargo-chef + build deps (libchafa-dev, pkg-config)
2. **planner**: `cargo chef prepare` -> recipe.json (only changes when Cargo.toml/lock change)
3. **builder**: `cargo chef cook` (cached deps) + `cargo build --release`
4. **runtime**: debian:trixie-slim + binary + libchafa0t64

Build time with warm cache: 15-30 seconds for code-only changes.

## Dockerfile Skeleton

```dockerfile
# syntax=docker/dockerfile:1

# --- Stage 1: Base with build tools ---
FROM rust:1.86-slim-trixie AS base
RUN apt-get update && apt-get install -y --no-install-recommends \
    pkg-config libchafa-dev libglib2.0-dev ca-certificates \
    && rm -rf /var/lib/apt/lists/*
RUN cargo install cargo-chef --locked
WORKDIR /app

# --- Stage 2: Plan dependencies ---
FROM base AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

# --- Stage 3: Build ---
FROM base AS builder
COPY --from=planner /app/recipe.json recipe.json
RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \
    --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \
    cargo chef cook --release --recipe-path recipe.json
COPY . .
RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \
    --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \
    cargo build --release --bin repartee

# --- Stage 4: Runtime ---
FROM debian:trixie-slim AS runtime
RUN apt-get update && apt-get install -y --no-install-recommends \
    libchafa0t64 ca-certificates \
    && rm -rf /var/lib/apt/lists/*
RUN groupadd --system --gid 1001 repartee && \
    useradd --system --uid 1001 --gid repartee --create-home repartee
COPY --from=builder --chown=repartee:repartee \
    /app/target/release/repartee /usr/local/bin/repartee
USER repartee
ENTRYPOINT ["/usr/local/bin/repartee"]
```

## Estimated Image Size

| Component | Size |
|---|---|
| debian:trixie-slim base | ~75 MB |
| libchafa0t64 + libglib deps | ~5-8 MB |
| ca-certificates | ~0.5 MB |
| repartee binary (stripped) | ~20 MB |
| **Total** | **~100-105 MB** |

## Feature Flag Option (future)

Make ratatui-image + chafa optional via `default = ["image-preview"]`.
- `repartee:latest` — full image with chafa (~100MB, debian-slim)
- `repartee:slim` — no image preview (~20MB, scratch)

## Multi-Platform (AMD64 + ARM64)

Best approach: parallel native builds on each arch, then combine:
```bash
docker buildx imagetools create \
  -t ghcr.io/outragedevs/repartee:latest \
  ghcr.io/outragedevs/repartee:amd64 \
  ghcr.io/outragedevs/repartee:arm64
```

## Security

- Non-root user (uid 1001)
- `--no-install-recommends` on apt-get
- Pin base images by digest in production
- Consider cosign image signing + SBOM attestations
- Trivy vulnerability scanning in CI

## chafa in Docker Context

Docker CAN run TUI apps with `docker run -it`. Image preview via chafa works
because the container outputs terminal escape sequences — the user's terminal
outside Docker renders them. So chafa is useful in Docker for interactive use.

| Use case | TUI? | Image preview? | Needs chafa? |
|----------|------|----------------|--------------|
| `docker run -it repartee` | Yes | Yes | Yes |
| `docker run -d repartee -d` (headless) | No | No | No |
| Detach + reattach | On reattach | On reattach | Yes |
