Docker

Day-to-day usage — once images are built, skip the rebuild to start in seconds:

Synced from Prax at f62d7985 View source ↗

← Infrastructure

cp .env-example .env    # configure API keys
docker compose up --build

Day-to-day usage — once images are built, skip the rebuild to start in seconds:

docker compose up                         # start with existing images (fast)
docker compose up --build                 # rebuild ALL images then start
docker compose up --build prax            # rebuild only the prax image, start everything
docker compose up --build sandbox         # rebuild only the sandbox image, start everything
docker compose build prax && docker compose up   # same idea, explicit two-step

Use --build when you’ve changed a Dockerfile or its dependencies (e.g. added a package). For code-only changes in dev mode, plain docker compose up is enough.

Dev mode — mount local source code so changes auto-reload without rebuilding:

docker compose -f docker-compose.yml -f docker-compose.dev.yml up

This bind-mounts prax/, app.py, config.py, and scripts/ into the container and sets DEBUG=true, which enables Flask’s Werkzeug reloader. Edit code locally, save, and the app restarts automatically. You still need --build if you change the Dockerfile, pyproject.toml, or system-level dependencies.

This starts two core services (the prax container is all-in-one):

Service Description
prax All-in-one container that bundles the Flask app (port 5001), the TeamWork web UI (port 3000) + API (port 8000), Qdrant, Neo4j, and ngrok (dashboard on 4040). .env injected, Docker socket for sandbox management. ngrok forwards the Twilio webhook routes (/transcribe, /sms) and the gated /shared/<token> endpoint to the public internet — only files/courses/notes registered in workspaces/{user}/.shares.json are reachable through it.
sandbox Always-on pure-execution sandbox with Python + scientific stack, DuckDB, Lean, LaTeX, ffmpeg, poppler, pandoc, headless Chrome, and desktop. Ships no coding-agent server (no OpenCode/Claude-Code/Codex) and takes no model API keys — Prax codes natively. Shares ./workspaces volume.
tailscale (opt-in) Userspace tailscaled sidecar that joins your tailnet and serves TeamWork (:443) + Grafana (:3001) over MagicDNS HTTPS. Activated by setting TS_AUTHKEY + COMPOSE_PROFILES=tailscale in .env; silently skipped otherwise. State persists in a Docker volume so the node identity survives restarts.

The app waits for the sandbox and TeamWork health checks before starting. Environment detection is automatic — RUNNING_IN_DOCKER=true and SANDBOX_HOST=sandbox are set by compose.

With observability — add --profile observability to start Tempo, Loki, Prometheus, Promtail, and Grafana alongside the core services:

docker compose --profile observability up --build

This adds five services (Tempo :4318, Loki :3100, Promtail, Prometheus :9090, Grafana :3002). See Observability for details. Safe to leave OBSERVABILITY_ENABLED=true in .env — Prax probes Tempo at startup and silently disables tracing if it’s unreachable.

Runtime capabilities in Docker mode:

  • sandbox_install("package") — apt-get install inside the running sandbox
  • sandbox_rebuild() — Prax edits the Dockerfile, rebuilds the image, and restarts the container
  • workspace_share_file("path/to/file.mp4") — publish a single file at a public ngrok URL (explicit user consent only — file is added to the share registry; revoke via workspace_unshare_file(token), audit via workspace_list_shares())

Standalone (without compose)

docker build -t prax .

docker run -d -p 5001:5001 --restart always \
  -v "$HOME/workspaces:/app/workspaces" \
  -v /var/run/docker.sock:/var/run/docker.sock \
  prax

Build the sandbox image separately (it lives in the sibling prax-sandbox repo):

cd ../prax-sandbox && make build          # -> prax-sandbox:latest