Container Runtime

May 25, 2026 ยท View on GitHub

Perseus does not require containers, but it can run as an OCI-style local image when a team wants a sidecar, a reproducible helper, or an isolated service process. The image still uses the single-file runtime: perseus.py is copied directly into the image and exposed as perseus.

Build

Use any Docker-compatible or OCI-compatible builder:

docker build -t perseus:local .

Podman and other compatible builders can use the same Dockerfile if they support standard Dockerfile syntax.

Render A Mounted Workspace

The default compose service renders the repository's .perseus/context.md into the named Perseus home volume:

docker compose run --rm render

For an ad hoc run, mount the workspace read-only and keep Perseus state in a separate volume:

docker run --rm \
  --mount type=bind,source="$PWD",target=/workspace,readonly \
  --mount type=volume,source=perseus-home,target=/perseus-home \
  -e PERSEUS_HOME=/perseus-home \
  perseus:local render /workspace/.perseus/context.md --output /perseus-home/rendered-context.md

On shells that do not expose PWD, replace source="$PWD" with the absolute path to the workspace.

Authenticated Serve

perseus serve refuses non-loopback binds unless bearer auth is configured or the user explicitly opts into insecure remote access. Inside a container, the process binds 0.0.0.0 so the port can be published, while the compose example publishes only to host loopback:

docker compose --profile serve up serve

The compose file mounts examples/container/config.yaml at /perseus-home/config.yaml. Replace change-me-before-serving with a token from:

docker run --rm perseus:local serve --generate-token

Clients must send:

Authorization: Bearer change-me-before-serving

Watch In A Container

For a foreground sidecar that keeps render outputs fresh without host scheduler setup, run the same image with perseus watch:

docker run --rm \
  --mount type=bind,source="$PWD",target=/workspace,readonly \
  --mount type=volume,source=perseus-home,target=/perseus-home \
  -e PERSEUS_HOME=/perseus-home \
  perseus:local watch --source /workspace/.perseus/context.md \
    --output /perseus-home/rendered-context.md \
    --allow-outside-workspace

If the mounted workspace contains .perseus/pack.yaml, omit --source and --output to refresh the pack's renders: targets.

Trust Notes

  • Mount workspaces read-only unless Perseus is intentionally writing rendered output back into the project.
  • Treat /perseus-home as stateful: it can contain config, auth tokens, cache, checkpoints, audit logs, Mneme data, inbox messages, and Pythia logs.
  • Do not mount the host container socket into the Perseus container.
  • Keep published ports loopback-bound unless the token and network boundary are intentional.
  • read_only: true and a /tmp tmpfs are useful hardening defaults for serve mode. Keep /perseus-home writable if you want audit logs and cache writes.
  • Local or OpenAI-compatible LLM endpoints must be configured explicitly and made reachable from the container network.