OpenWork Host (Docker)
Dev testability stack (recommended for testing)
One command, no custom Dockerfile. Uses node:22-bookworm-slim off the shelf.
From the repo root:
./packaging/docker/dev-up.sh
Then open the printed Web UI URL (ports are randomized so you can run multiple stacks).
What it does:
- Starts headless (OpenCode + OpenWork server) on port 8787
- Starts web UI (Vite dev server) on port 5173
- Auto-generates and shares auth tokens between services
- Web waits for headless health check before starting
- Builds Linux binaries inside the container (no host binary conflicts)
- Uses an isolated OpenCode dev state by default so the stack does not read your personal host config/auth/data
If you want to seed the container from your host OpenCode state for debugging, run with OPENWORK_DOCKER_DEV_MOUNT_HOST_OPENCODE=1. This imports host config/auth into the isolated dev state instead of mounting live host state directly.
Useful commands:
- Logs:
docker compose -p <project> -f packaging/docker/docker-compose.dev.yml logs - Tear down:
docker compose -p <project> -f packaging/docker/docker-compose.dev.yml down - Health check:
curl http://localhost:<openwork_port>/health
Optional env vars (via .env or export):
OPENWORK_TOKEN— fixed client tokenOPENWORK_HOST_TOKEN— fixed host/admin tokenOPENWORK_WORKSPACE— host path to mount as workspaceOPENWORK_PORT— host port to map to container :8787WEB_PORT— host port to map to container :5173OPENWORK_DOCKER_DEV_MOUNT_HOST_OPENCODE=1— import host OpenCode config/auth into the isolated dev stateOPENWORK_OPENCODE_CONFIG_DIR— override the host OpenCode config source used for that optional importOPENWORK_OPENCODE_DATA_DIR— override the host OpenCode data source used for that optional import
Den local stack (Docker)
One command for the Den control plane, local MySQL, and the cloud web app.
From the repo root:
./packaging/docker/den-dev-up.sh
Or via pnpm:
pnpm dev:den-docker
What it does:
- Starts MySQL for the Den service
- Starts Den control plane on port 8788 inside Docker with
PROVISIONER_MODE=stub - Runs Den migrations automatically before the API starts
- Starts the OpenWork Cloud web app on port 3005 inside Docker
- Points the web app's auth + API proxy routes at the local Den service
- Prints randomized host URLs so multiple stacks can run side by side
Useful commands:
- Logs:
docker compose -p <project> -f packaging/docker/docker-compose.den-dev.yml logs - Tear down:
docker compose -p <project> -f packaging/docker/docker-compose.den-dev.yml down - Tear down + reset DB:
docker compose -p <project> -f packaging/docker/docker-compose.den-dev.yml down -v
Optional env vars (via .env or export):
DEN_API_PORT— host port to map to the Den control plane :8788DEN_WEB_PORT— host port to map to the cloud web app :3005DEN_BETTER_AUTH_SECRET— Better Auth secret (auto-generated if unset)DEN_BETTER_AUTH_URL— browser-facing auth base URL (defaults to the printed web URL)DEN_CORS_ORIGINS— trusted origins for Better Auth + Express CORSDEN_PROVISIONER_MODE—stuborrender(defaults tostub)DEN_WORKER_URL_TEMPLATE— stub worker URL template with{workerId}placeholder
Production container
This is a minimal packaging template to run the OpenWork Host contract in a single container.
It runs:
opencode serve(engine) bound to127.0.0.1:4096inside the containeropenwork-serverbound to0.0.0.0:8787(the only published surface)
Local run (compose)
From this directory:
docker compose up --build
Then open:
http://127.0.0.1:8787/ui
Config
Recommended env vars:
OPENWORK_TOKEN(client token)OPENWORK_HOST_TOKEN(host/owner token)
Optional:
OPENWORK_APPROVAL_MODE=auto|manualOPENWORK_APPROVAL_TIMEOUT_MS=30000
Persistence:
- Workspace is mounted at
/workspace - Host data dir is mounted at
/data(OpenCode caches + OpenWork server config/tokens)
Notes
- OpenCode is not exposed directly; access it via the OpenWork proxy (
/opencode/*). - For PaaS, replace
./workspace:/workspacewith a volume or a checkout strategy (git clone on boot).