maestro/docs/docker.md
oss-sync 00bf2ea16f
Some checks failed
CI / build-and-test (push) Has been cancelled
sync: update from private repo (1a0e50d)
2026-06-16 03:30:34 +00:00

5.4 KiB

English | 日本語

Running MAESTRO with Docker

The fastest way to run MAESTRO is Docker Compose. This guide covers the full path from git clone to a working instance, plus the things that commonly trip people up (Linux networking, the LLM endpoint, data persistence, the sandbox).

TL;DR

cp .env.example .env     # point OLLAMA_BASE_URL/OLLAMA_MODEL at your LLM
docker compose up -d     # builds the image on first run, then starts
# open http://localhost:9876

Compose publishes the UI on 127.0.0.1:9876 only, so a fresh instance is not reachable from your LAN. See Going beyond localhost.

What the container is (and is not)

  • It runs the MAESTRO app (web UI, workers, tools, optional gateway).
  • It does not run an LLM. You point MAESTRO at an existing OpenAI-compatible endpoint (Ollama, vLLM, a hosted gateway, …).
  • The image bundles the headed-browser stack (Xvfb / x11vnc / Chromium) and the Bash sandbox (bubblewrap + a pre-baked Python toolchain), so the Browser tab and sandboxed Bash work out of the box.

The LLM endpoint

.env.example defaults to an Ollama running on the host:

OLLAMA_BASE_URL=http://host.docker.internal:11434/v1
OLLAMA_MODEL=qwen3:32b

host.docker.internal resolves to the host on Docker Desktop (macOS/Windows) and — because docker-compose.yml sets extra_hosts: host.docker.internal:host-gateway — on Linux too. You usually don't need to change anything.

Point it elsewhere when your LLM is not on the Docker host:

# Ollama / vLLM on another machine (use that machine's IP)
OLLAMA_BASE_URL=http://192.0.2.10:11434/v1
# A hosted OpenAI-compatible gateway
OLLAMA_BASE_URL=https://your-gateway.example.com/v1

Make sure the model in OLLAMA_MODEL is actually pulled/served by that endpoint, or task runs will fail at the first LLM call.

Verify it's running

docker compose ps                 # STATUS should become healthy
docker compose logs -f maestro    # watch startup; Ctrl-C to stop following

The container has a healthcheck that polls /health. Once it reports healthy, open http://localhost:9876, create a task, and confirm it progresses. If the LLM endpoint is wrong you'll see connection errors in the logs as soon as a task starts.

Data persistence

Two named volumes survive docker compose down / image rebuilds:

Volume Mount Holds
maestro-data /app/data SQLite DB, users, skills, secrets
maestro-workspaces /workspaces per-task agent workspaces

docker compose down -v deletes these volumes (and all your data) — omit -v to keep them.

Configuration

The image ships a runnable config.yaml (copied from config.yaml.example), and .env overrides the common knobs (LLM endpoint, PORT). For most setups, editing .env is all you need.

To manage the full config.yaml from the host (and have Settings UI edits persist across container recreation), bind-mount it — uncomment in docker-compose.yml:

    volumes:
      - ./config.yaml:/app/config.yaml   # create ./config.yaml first

Create the host file before starting (cp config.yaml.example config.yaml), or Docker will create a directory at that path. Without the bind-mount, Settings UI changes live only inside the container and are lost when it is recreated.

The Bash sandbox in Docker

safety.bash_sandbox defaults to auto: use bubblewrap when available, fall back to a hardened allowlist otherwise. The image installs bubblewrap, so the sandbox is active by default. For multi-user or untrusted workloads set safety.bash_sandbox: always (fail-closed if bubblewrap is unavailable).

bubblewrap needs unprivileged user namespaces. They are enabled on most modern hosts; if your host or container runtime disables them, auto degrades to the hardened allowlist and logs a warning at startup. See operations/bash-sandbox-provisioning.md.

Build vs. prebuilt image

docker compose up builds the image locally from the Dockerfile (there is no published image). The first build downloads Chromium and the Python toolchain, so expect several minutes; later starts reuse the cached image. Rebuild after pulling new code with docker compose up -d --build.

Going beyond localhost

The default binding is intentionally local-only. Before exposing MAESTRO to a network:

  1. Enable authentication (OAuth, or local accounts).
  2. Set safety.bash_sandbox: always.
  3. Terminate TLS — either MAESTRO's native HTTPS or a reverse proxy in front.
  4. Change the compose port mapping from 127.0.0.1:9876:9876 to the interface you intend to serve.

See SECURITY.md and getting-started.md for the full hardening checklist.

Troubleshooting

Symptom Likely cause
Tasks fail immediately with a connection error OLLAMA_BASE_URL unreachable from the container, or the model isn't served
host.docker.internal not found (Linux) extra_hosts removed from compose, or an old Docker without host-gateway — use the host's LAN IP
Settings changes vanish after down/up config.yaml not bind-mounted (see Configuration)
Browser tab / CAPTCHA pool unstable /dev/shm too small — compose sets shm_size: 1gb; keep it
All data gone after restart used docker compose down -v (the -v deletes volumes)