services: # Ollama sidecar — embedding service so users don't need Ollama on their # host. This image BAKES bge-m3 (~1.1GB) at build time and its entrypoint # seeds it into the store before serving, so the container reaches # embedding-ready with ZERO network pull (offline / China-network friendly). # The daemon runs on the internal Docker network at http://ollama:11434; # the backend's [llm.embedding] is seeded to point here on first bootstrap. # # Disable this entire block by removing it (and the depends_on + # OPENBILICLAW_SEED_OLLAMA_DEFAULTS env in the backend service) if # you'd rather run an embedding API key from a cloud provider — see # docs/docker-deployment.md. ollama: build: context: . dockerfile: docker/ollama-bundled.Dockerfile container_name: openbiliclaw-ollama volumes: - openbiliclaw_ollama:/root/.ollama # No custom entrypoint / runtime pull: the bundled image self-seeds the # baked model on start. Set OPENBILICLAW_OLLAMA_ALLOW_PULL=1 to opt into a # network pull if the baked seed is ever missing/corrupt (default: fail # loud via the healthcheck instead of silently degrading). healthcheck: # Healthy = daemon up AND bge-m3 is locally available. With the baked # seed this greens up in seconds; start_period stays generous only for # the opt-in runtime-pull fallback. test: ["CMD-SHELL", "ollama list 2>/dev/null | grep -q '^bge-m3'"] interval: 30s timeout: 10s retries: 6 start_period: 300s restart: unless-stopped openbiliclaw-backend: build: context: . dockerfile: Dockerfile # The Dockerfile only depends on python:3.11-slim, which is # published as a multi-arch manifest. ``docker compose build`` # picks the architecture matching the host (amd64 on Intel, # arm64 on Apple Silicon / Raspberry Pi). To explicitly cross- # build a release image, use buildx: # docker buildx build --platform linux/amd64,linux/arm64 \ # -t openbiliclaw-backend:vX.Y.Z . container_name: openbiliclaw-backend depends_on: # service_started (not service_healthy) on purpose: the sidecar is # only "healthy" once bge-m3 finished downloading (~1.1GB). If that # first pull fails or crawls on a slow network, a service_healthy # gate would keep the backend from EVER starting — the user gets a # dead install with no UI to see why. Instead the backend boots # immediately; the /setup/ wizard and init prereq checks surface # "embedding not ready yet" until the pull completes. ollama: condition: service_started environment: OPENBILICLAW_PROJECT_ROOT: /app/runtime OPENBILICLAW_CONFIG_TEMPLATE: /app/config.example.toml OPENBILICLAW_PROXY_HOST: ${OPENBILICLAW_PROXY_HOST:-host.docker.internal} OPENBILICLAW_PROXY_PORT: ${OPENBILICLAW_PROXY_PORT:-7897} OPENBILICLAW_PROXY_TIMEOUT: ${OPENBILICLAW_PROXY_TIMEOUT:-1.0} # On first config bootstrap, seed [llm.ollama] base_url and # [llm.embedding] to point at the bundled sidecar above. Lets # Docker users have local embedding out of the box, even if they # later pick OpenAI / Claude / etc for chat. Existing config.toml # is never overwritten. OPENBILICLAW_SEED_OLLAMA_DEFAULTS: "1" OPENBILICLAW_OLLAMA_BASE_URL: "http://ollama:11434/v1" OPENBILICLAW_EMBEDDING_MODEL: "bge-m3" # OPENBILICLAW_XHS_SIDECAR_URL: http://xhs-sidecar:5556 # sidecar removed — extension extracts metadata from DOM command: - python - -m - openbiliclaw.docker_runtime - openbiliclaw - serve-api - --host - 0.0.0.0 - --port - "8420" # ``host.docker.internal`` resolves the host machine from inside # the container. Used by: # - HTTP proxy auto-detect (OPENBILICLAW_PROXY_HOST) # - any user that picks "use my host's Ollama instead of the # bundled sidecar" by overriding OPENBILICLAW_OLLAMA_BASE_URL # Required on Linux Docker; auto-provided by Docker Desktop on # Mac / Windows. The ``host-gateway`` magic value tells the engine # to inject the right address per platform. extra_hosts: - "host.docker.internal:host-gateway" ports: - "8420:8420" volumes: - openbiliclaw_config:/app/runtime - openbiliclaw_data:/app/runtime/data - openbiliclaw_logs:/app/runtime/logs # Compose-level healthcheck mirrors the Dockerfile HEALTHCHECK so # ``docker compose ps`` shows ``healthy`` only when /api/health # returns 200, not just when the container process is alive. healthcheck: test: ["CMD", "python", "-c", "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8420/api/health', timeout=4).status==200 else 1)"] interval: 30s timeout: 5s start_period: 20s retries: 3 restart: unless-stopped # TLS reverse proxy — *optional* LAN/self-managed HTTPS component. # Only started with `docker compose --profile tls up`. Terminates TLS with # the project's self-signed cert and forwards to the backend over the # internal network. See docs/https-deployment.md for non-Docker setups. openbiliclaw-tls-proxy: profiles: - tls build: context: . dockerfile: docker/openbiliclaw-tls-proxy.Dockerfile # In-container cert directory; overridable at build time. args: CERT_DIR: /certs container_name: openbiliclaw-tls-proxy depends_on: openbiliclaw-backend: condition: service_healthy ports: - "${OPENBILICLAW_TLS_PORT:-8443}:${OPENBILICLAW_TLS_PORT:-8443}" volumes: # Docker-managed volume — no host path needed. # Proxy auto-generates CA+server certs if the volume is empty # (new deployments). Migrate existing certs in with a one-off: # docker run --rm -v openbiliclaw_certs:/dst \ # -v /host/certs:/src:ro busybox cp /src/*.{crt,key,crl} /dst/ - openbiliclaw_certs:/certs environment: BACKEND_HOST: openbiliclaw-backend BACKEND_PORT: "8420" LISTEN_PORT: "${OPENBILICLAW_TLS_PORT:-8443}" CERT_DIR: /certs # Comma-separated hostname/IP SANs used by LAN clients. Set this # before the first start, for example: # OPENBILICLAW_TLS_SAN_NAMES=192.168.1.20,openbiliclaw.lan SAN_NAMES: "${OPENBILICLAW_TLS_SAN_NAMES:-}" # Set to "0" to disable auto-generation and require you to supply # your own srv.crt / srv.key in the certs volume. AUTO_GEN_CERTS: "${OPENBILICLAW_TLS_AUTO_GEN_CERTS:-1}" healthcheck: test: ["CMD", "python", "-c", "import os,ssl,urllib.request,sys; port=os.environ.get('LISTEN_PORT','8443'); ctx=ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE; sys.exit(0 if urllib.request.urlopen(f'https://127.0.0.1:{port}/healthz', context=ctx, timeout=4).status==200 else 1)"] interval: 30s timeout: 5s start_period: 10s retries: 3 restart: unless-stopped volumes: openbiliclaw_config: openbiliclaw_data: openbiliclaw_logs: # Persists ollama models across container recreations so users don't # have to re-pull bge-m3 on every rebuild. openbiliclaw_ollama: # Holds the TLS certificate chain (ca.crt/ca.key, srv.crt/srv.key, ca.crl). # Auto-generated on first startup when empty; persists across rebuilds. # Explicit name prevents compose from adding the project-name prefix. openbiliclaw_certs: name: openbiliclaw_certs