Docker
Day-to-day usage — once images are built, skip the rebuild to start in seconds:
f62d7985
View source ↗
Docker Compose (recommended)
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 sandboxsandbox_rebuild()— Prax edits the Dockerfile, rebuilds the image, and restarts the containerworkspace_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 viaworkspace_unshare_file(token), audit viaworkspace_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