# CanLex MCP server -- remote (streamable-HTTP) image. # # Builds anywhere: Hugging Face Spaces, Google Cloud Run, Fly.io, plain Docker. # Retrieval is fully local and key-free; the optional CanLII case citator reads # its key from the CANLII_API_KEY environment variable (supplied as a host # secret -- the key is never copied into the image). FROM python:3.12-slim # libgomp1 is the OpenMP runtime that onnxruntime (the reranker) links against. RUN apt-get update \ && apt-get install -y --no-install-recommends libgomp1 \ && rm -rf /var/lib/apt/lists/* # Run as a non-root user (UID 1000) -- required by Hugging Face Spaces. RUN useradd --create-home --home-dir /app --uid 1000 app WORKDIR /app # Python dependencies first, so this layer caches across code changes. COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Application code, the processed corpus (section-chunk JSON), and the prebuilt # semantic embeddings (embeddings.npz, committed via git-LFS). Shipping the # embeddings as an artifact keeps the build fast: embedding ~20k chunks on the # build host took ~33 min and was tripping Hugging Face's job timeout as the # corpus grew. Regenerate with 'python -m canlex.embed' after any corpus change # and commit the result. COPY --chown=app:app canlex/ ./canlex/ COPY --chown=app:app data/processed/*.json ./data/processed/ COPY --chown=app:app data/processed/embeddings.npz ./data/processed/ USER app ENV HOME=/app \ HF_HOME=/app/.hf_cache \ CANLEX_HTTP=1 \ PORT=7860 \ PYTHONUNBUFFERED=1 # Pre-fetch the embedder and cross-encoder models so the cache is baked into the # image and the first request needs no network. The corpus is NOT re-embedded # here -- the committed embeddings.npz is used as-is; only the bge query model # (for embedding live queries) and the reranker are downloaded. RUN python -c "from canlex.embed import Embedder; Embedder()" \ && python -c "from canlex.rerank import Reranker; Reranker()" # From here on, model files are served from the baked cache, never fetched. ENV HF_HUB_OFFLINE=1 EXPOSE 7860 CMD ["python", "-m", "canlex.server"]