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

# Container images

> The control-plane and workspace images, what they contain, and how to build them yourself.

r5d.chat publishes two images per release to GHCR.

| Image                                   | Purpose                                         | Base                     |
| --------------------------------------- | ----------------------------------------------- | ------------------------ |
| `ghcr.io/ricsam/r5d-chat-control-plane` | Web application, API, and Kubernetes reconciler | `oven/bun:1.3.14-alpine` |
| `ghcr.io/ricsam/r5d-chat-workspace`     | The per-user agent environment                  | `oven/bun:1.3.14-debian` |

Both are tagged with the release version and `latest`. Always deploy an explicit
version in production.

```bash theme={null}
docker pull ghcr.io/ricsam/r5d-chat-control-plane:0.1.0
docker pull ghcr.io/ricsam/r5d-chat-workspace:0.1.0
```

## The control-plane image

A small multi-stage build. Dependencies install first, the application is
typechecked and built, and the runtime stage keeps only the build output,
migrations, and production dependencies. It runs as the unprivileged `bun` user
and listens on port 3000.

The chart runs the same image as an init container with `bun run db:migrate` to
apply database migrations before the application starts. Migrations take a
PostgreSQL advisory lock, so parallel rollouts cannot race.

## The workspace image

The workspace is deliberately batteries-included: it is the general-purpose
environment where user work happens, and a missing tool means a failed task.

<AccordionGroup>
  <Accordion title="Development" icon="code">
    Bun and bunx, Node.js with npm/npx, Python 3 with pip/venv/pytest, C/C++
    build tools, CMake, pkg-config, Git and Git LFS, GitHub CLI, shellcheck,
    ripgrep, jq, yq, tmux, and common editors and archive utilities.
  </Accordion>

  <Accordion title="Data and plotting" icon="chart-line">
    NumPy, pandas, SciPy, Matplotlib, Seaborn, Pillow, BeautifulSoup, lxml,
    requests, SQLite, PostgreSQL and Redis clients, and Graphviz.
  </Accordion>

  <Accordion title="Images and video" icon="image">
    FFmpeg and ffprobe, ImageMagick, libvips, ExifTool, MediaInfo, gifsicle, WebP,
    pngquant, optipng, jpegoptim, librsvg, Tesseract OCR, and broad Noto and
    DejaVu font coverage including CJK and emoji.
  </Accordion>

  <Accordion title="Documents" icon="file-lines">
    LibreOffice headless, Pandoc, Poppler, qpdf, Ghostscript, antiword, unrtf,
    Recoll and Xapian for ranked full-text search, and the Python `python-docx`,
    `openpyxl`, and `python-pptx` libraries.
  </Accordion>
</AccordionGroup>

The image also bundles agent skills at `/opt/r5dchat/skills` for producing
documents, spreadsheets, slides, and PDFs.

<Note>
  Java, Go, Rust, browser automation, TeX, geospatial tooling, and GPU runtimes
  are intentionally excluded to keep the image manageable. Agents can install
  them on demand, or you can build a variant image.
</Note>

### Persistence inside a workspace

Only `/home/r5d` is on the persistent volume. Packages an agent installs into
system paths at runtime disappear when the pod scales to zero. Add broadly
useful tools to the image instead of relying on ad-hoc installs.

## Build the images yourself

Both Dockerfiles build from the repository root.

```bash theme={null}
docker build -f images/control-plane/Dockerfile -t r5d-chat-control-plane:test .
docker build -f images/workspace/Dockerfile -t r5d-chat-workspace:test .
```

Smoke-test the workspace image before rolling it out:

```bash theme={null}
docker run --rm --entrypoint sh r5d-chat-workspace:test -c '
  set -eu
  for tool in bun node npm python3 pip3 git rg ffmpeg ffprobe magick vips \
    exiftool mediainfo libreoffice pandoc pdftotext qpdf tesseract \
    recollq recollindex; do command -v "$tool" >/dev/null; done
  python3 -c "import matplotlib, numpy, openpyxl, pandas, PIL, pptx, scipy, seaborn"
'
```

## Publish to your own registry

If you maintain a fork or need images in a private registry, build and push with
an immutable tag, then point the chart at them:

```bash theme={null}
REGISTRY=ghcr.io/your-org
TAG="deploy-$(date -u +%Y%m%d%H%M%S)-$(git rev-parse --short HEAD)"

docker build -f images/control-plane/Dockerfile \
  -t "$REGISTRY/r5d-chat-control-plane:$TAG" .
docker build -f images/workspace/Dockerfile \
  -t "$REGISTRY/r5d-chat-workspace:$TAG" .

docker push "$REGISTRY/r5d-chat-control-plane:$TAG"
docker push "$REGISTRY/r5d-chat-workspace:$TAG"
```

```yaml theme={null}
image:
  repository: ghcr.io/your-org/r5d-chat-control-plane
  tag: deploy-20250219120000-abc1234
workspaceImage:
  repository: ghcr.io/your-org/r5d-chat-workspace
  tag: deploy-20250219120000-abc1234
```

<Card title="Rolling out a new workspace image" icon="arrows-rotate" href="/operate/upgrades">
  Existing workspace Deployments need an explicit image update.
</Card>
