leankg 0.19.13

Lightweight Knowledge Graph for AI-Assisted Development
services:
  leankg:
    # Pull from Docker Hub by default — no local rebuild.
    # To publish a new image: docker compose -f docker-compose.build.yml build
    image: ${LEANKG_IMAGE:-freepeak/leankg:latest}
    pull_policy: ${LEANKG_PULL_POLICY:-missing}
    env_file:
      # Local-only configuration that overrides the defaults below. This file
      # is .gitignored so user-specific host paths and project locations never
      # leak into the committed compose file. Copy `.dockerfile.example` to
      # `.dockerfile` and edit for your environment.
      - path: ./.dockerfile
        required: false
    environment:
      LEANKG_DB_ENGINE: rocksdb
      LEANKG_ROCKSDB_ROOT: /data/leankg-rocksdb
      MCP_HTTP_PORT: "9699"
      LEANKG_AUTO_INDEX: "1"
      # Plan §"Part B" defaults: never block MCP on embed. The MCP server
      # owns the in-process background embed; LEANKG_EMBED_BACKGROUND_* knobs
      # let operators tune workers/batch/full-rebuild at runtime. Set
      # LEANKG_EMBED_BACKGROUND=0 to opt out and rely on the legacy
      # foreground `leankg embed --wait` (off by default).
      # Offline cold embed via docker-compose.embed.yml. Keep BACKGROUND off
      # so MCP does not drop HNSW mid-query (override .dockerfile if needed).
      LEANKG_EMBED_ON_BOOT: "0"
      LEANKG_EMBED_BACKGROUND: "0"
      LEANKG_EMBED_FAST: "1"
      LEANKG_EMBED_MODEL: "bge-q"
      LEANKG_EMBED_MAX_SEQ: "128"
      LEANKG_EMBED_MAX_BLOB_CHARS: "500"
      # Soft pause budget must fit under mem_limit 2g (Local survival).
      # Offline full rebuild uses docker-compose.embed.yml (higher mem_limit).
      LEANKG_EMBED_MAX_MB: "512"
      LEANKG_EMBED_BACKGROUND_WORKERS: "1"
      LEANKG_EMBED_BACKGROUND_BATCH: "32"
      # `LEANKG_MCP_PROJECT` and `LEANKG_PROJECT_DIRS` are intentionally
      # NOT set here. With both `env_file` (`.dockerfile`) and `environment:`
      # declaring the same key, Compose lets `environment:` win, which silently
      # ignored user overrides. The defaults live in `entrypoint.sh`:
      #   LEANKG_MCP_PROJECT    -> /workspace if unset
      #   LEANKG_PROJECT_DIRS   -> unset (entrypoint falls back to /workspace* glob)
      # Override both by setting them in `.dockerfile` (comma-separated for
      # LEANKG_PROJECT_DIRS, matching `entrypoint.sh`'s `IFS=','`).
      # Lower mmap default to keep RSS bounded; the previous 256 MiB blew
      # containers past the macOS Docker Desktop limit and triggered OOM kills.
      LEANKG_MMAP_SIZE: "67108864"
      # Slower, larger debounce window absorbs git-pull / build storms.
      LEANKG_WATCHER_DEBOUNCE_MS: "2000"
      LEANKG_WATCHER_BURST_LIMIT: "256"
      RUST_LOG: "leankg=info"
      # Option A: REST API for UI v2 alongside MCP (entrypoint starts `leankg serve`).
      # Set LEANKG_SERVE_HTTP=0 in .dockerfile to disable and keep MCP-only.
      LEANKG_SERVE_HTTP: "1"
      LEANKG_SERVE_PORT: "8080"
    ports:
      - "9699:9699"
      - "8080:8080"
    volumes:
      # Primary project mount (the LeanKG source tree itself, used by the
      # auto-init fallback path). The host side is taken from HOST_PROJECT_PATH
      # (default: the current dir). Override via .dockerfile.
      - ${HOST_PROJECT_PATH:-./}:${CONTAINER_PROJECT_PATH:-/workspace}
      - leankg-rocksdb:/data/leankg-rocksdb
      # Persist ONNX / tokenizer cache across restarts (Embedder + DirectEmbedder).
      - leankg_models:/root/.cache/leankg
    working_dir: ${CONTAINER_PROJECT_PATH:-/workspace}
    # Resource limits — multi-project / mega-graph MCP envelope (embed report
    # 2026-07-17/18): ~147k vectors OOMed under 2g during semantic_search.
    # Defaults: mem_limit 6g, mem_reservation 3g, cpus 6. Single-project
    # LocalEngine survival KPI remains 2g (PRD §5.14) — lower via override
    # when not serving large side mounts.
    mem_limit: 6g
    mem_reservation: 3g
    cpus: "6"
    pids_limit: 4096
    restart: unless-stopped

volumes:
  leankg-rocksdb:
  leankg_models: