Deploy with Docker
This guide covers a production-ready Docker Compose deployment: building the image, mounting the workspace volume, wiring secrets via environment variables, and verifying health.
Prerequisites
Section titled “Prerequisites”- Docker >= 24
- Docker Compose v2
Docker Compose
Section titled “Docker Compose”A docker-compose.yml is provided at the project root. Adjust it for your environment:
services: workstacean: build: context: . target: production restart: unless-stopped env_file: .env environment: - WORKSPACE_DIR=/workspace - DATA_DIR=/data - TZ=America/New_York ports: # Expose the HTTP API on the host (adjust or remove for internal-only) - "3000:3000" # Expose the Astro dashboard + WebSocket event stream (disable with DISABLE_EVENT_VIEWER) - "8080:8080" volumes: # Workspace config (agents, goals, actions, ceremonies, domains) - ./workspace:/workspace # Persistent SQLite event log - data:/data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 5s retries: 3 start_period: 15s
volumes: data:Environment file
Section titled “Environment file”Create .env next to docker-compose.yml. This file is loaded by env_file and never committed to source control.
# ── Required ──────────────────────────────────────────────────────────────────ANTHROPIC_API_KEY=sk-ant-...WORKSTACEAN_API_KEY=change-me-in-production
# ── Optional: external A2A agents ─────────────────────────────────────────────AVA_BASE_URL=http://ava:3008AVA_API_KEY=your-ava-key
# ── Optional: Discord integration ─────────────────────────────────────────────DISCORD_BOT_TOKEN=Bot ...DISCORD_GUILD_ID=1234567890
# ── Optional: GitHub integration ──────────────────────────────────────────────GITHUB_TOKEN=ghp_...GITHUB_WEBHOOK_SECRET=your-webhook-secret
# ── Routing ───────────────────────────────────────────────────────────────────ROUTER_DEFAULT_SKILL=sitrep
# ── HTTP ──────────────────────────────────────────────────────────────────────WORKSTACEAN_HTTP_PORT=3000
# ── Storage ───────────────────────────────────────────────────────────────────WORKSPACE_DIR=/workspaceDATA_DIR=/dataFor a full list of all supported variables, see reference/env-vars.md.
Workspace volume
Section titled “Workspace volume”The workspace/ directory is mounted read-write so configuration changes can be applied without rebuilding the image:
./workspace/ ← bind-mounted to /workspace in container agents/ ava.yaml frank.yaml agents.yaml projects.yaml goals.yaml actions.yaml ceremonies/ daily-standup.yaml security-triage.yaml domains.yamlAfter editing any workspace file, restart the container:
docker compose restart workstaceanHot-reload for workspace YAML files is not supported in the current version (except projects.yaml and skill keywords via RouterPlugin).
Starting the stack
Section titled “Starting the stack”docker compose up -ddocker compose logs -f workstaceanExpected startup output:
[agent-runtime] loaded agent: ava (general, 1 skill) ← in-process chat agent[skill-broker] Registered 3 A2A agent(s) ← protomaker, quinn, etc.[ceremony-plugin] loaded 5 ceremonies[world-state] domain discovery: 3 domains registered[http] listening on :3000[workstacean] readyHealth check
Section titled “Health check”The /health endpoint returns 200 OK when the server is ready:
curl http://localhost:3000/health# {"status":"ok","uptime":42.3}Docker’s healthcheck (test: curl -f ...) will restart the container if this endpoint stops responding.
Dashboard
Section titled “Dashboard”The Astro dashboard is built during the Docker image build and served by the event-viewer plugin on port 8080. Once the stack is up:
open http://localhost:8080Set DISABLE_EVENT_VIEWER=1 in .env to skip the plugin entirely (e.g. for headless deployments). See the Dashboard reference for pages, API client, and cache behavior.
Production docker-compose with ava
Section titled “Production docker-compose with ava”If you run ava alongside workstacean in the same Compose project:
services: workstacean: build: . restart: unless-stopped env_file: .env environment: - WORKSPACE_DIR=/workspace - DATA_DIR=/data - AVA_BASE_URL=http://ava:3008 volumes: - ./workspace:/workspace - data:/data depends_on: ava: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 5s retries: 3
ava: image: protoLabsAI/protoMaker:latest restart: unless-stopped env_file: .env.ava healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3008/health"] interval: 30s timeout: 5s retries: 3
volumes: data:The AVA_BASE_URL=http://ava:3008 uses Docker’s internal DNS — the service name ava resolves automatically within the Compose network.
Securing the HTTP API
Section titled “Securing the HTTP API”The /publish endpoint requires X-API-Key: $WORKSTACEAN_API_KEY. Set a strong value in production. Other endpoints (/health, /api/world-state, etc.) do not require authentication by default — put workstacean behind a reverse proxy (nginx, Caddy) if you need to restrict access.
Persisting the event log
Section titled “Persisting the event log”The SQLite event log (DATA_DIR/events.db) records every bus message. Mount a named volume or host path to preserve it across container restarts:
volumes: - /srv/workstacean/data:/data