Spaces:
Sleeping
Sleeping
| # syntax=docker/dockerfile:1.7 | |
| # | |
| # Eolas backend container — FastAPI + LanceDB + fastembed. | |
| # | |
| # Strategy: | |
| # - Python 3.11-slim (small base; CPython is enough — onnxruntime brings perf) | |
| # - Install pip deps in their own layer so source edits don't bust the cache | |
| # - Pre-warm the BGE ONNX model at build time → first request has no 120 MB download | |
| # - Ship the LanceDB index inside the image (31 MB) → no volume needed in v0.3.0 | |
| # - Run uvicorn on $PORT (Fly sets this; defaults to 8080) | |
| # | |
| FROM python:3.11-slim AS runtime | |
| WORKDIR /app | |
| # Runtime libs onnxruntime needs (libgomp1 is the OpenMP runtime; the rest is | |
| # wheels). curl is here for the container HEALTHCHECK only. | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| libgomp1 \ | |
| curl \ | |
| && rm -rf /var/lib/apt/lists/* | |
| # ── Deps layer (cached unless pyproject.toml changes) ──────────────────────── | |
| COPY pyproject.toml ./ | |
| RUN pip install --no-cache-dir --upgrade pip \ | |
| && pip install --no-cache-dir \ | |
| "httpx>=0.27" \ | |
| "trafilatura>=1.12" \ | |
| "pymupdf>=1.24" \ | |
| "beautifulsoup4>=4.12" \ | |
| "lxml>=5.3" \ | |
| "tiktoken>=0.7" \ | |
| "lancedb>=0.13" \ | |
| "fastembed>=0.4" \ | |
| "rank-bm25>=0.2" \ | |
| "flashrank>=0.2" \ | |
| "fastapi>=0.111" \ | |
| "uvicorn[standard]>=0.30" \ | |
| "python-dotenv>=1.0" \ | |
| "sse-starlette>=2.1" \ | |
| "slowapi>=0.1.9" \ | |
| "google-genai>=0.3" \ | |
| "groq>=0.11" \ | |
| "openai>=1.40" \ | |
| "anthropic>=0.34" | |
| # ── Pre-warm the embedder + reranker models ───────────────────────────────── | |
| # bge-small-en-v1.5: ~120 MB ONNX. ms-marco-MiniLM-L-12-v2: ~22 MB ONNX. | |
| # Baked into the image so cold starts have no network fetch. | |
| RUN python -c "from fastembed import TextEmbedding; TextEmbedding('BAAI/bge-small-en-v1.5')" | |
| RUN python -c "from flashrank import Ranker; Ranker(model_name='ms-marco-MiniLM-L-12-v2')" | |
| # ── Application code + indexed corpus ──────────────────────────────────────── | |
| COPY app/ ./app/ | |
| COPY widget/ ./widget/ | |
| COPY data/lancedb/ ./data/lancedb/ | |
| # Runtime configuration | |
| ENV PYTHONUNBUFFERED=1 \ | |
| LOG_FORMAT=json \ | |
| LOG_LEVEL=INFO \ | |
| PORT=8080 \ | |
| LANCEDB_PATH=/app/data/lancedb \ | |
| LANCEDB_TABLE=chunks | |
| EXPOSE 8080 | |
| HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ | |
| CMD curl -fsS http://127.0.0.1:${PORT:-8080}/health || exit 1 | |
| # Single worker — the BGE model isn't cheap to load and one process saturates | |
| # a 1-core VM. Scale horizontally on Fly instead of forking workers. | |
| CMD ["sh", "-c", "uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-8080} --workers 1"] | |