Spaces:
Sleeping
Sleeping
| # SHL Assessment Recommender — production image. | |
| # | |
| # Ships the catalog + precomputed embeddings so nothing large downloads at boot | |
| # (CLAUDE.md §4). Binds to $PORT (Render/Fly/Railway/HF Spaces all set it). | |
| # /health answers immediately; the embedding model + indexes warm in a background | |
| # thread on startup (see app/main.py lifespan). | |
| FROM python:3.11-slim | |
| ENV PYTHONUNBUFFERED=1 \ | |
| PYTHONDONTWRITEBYTECODE=1 \ | |
| PIP_NO_CACHE_DIR=1 \ | |
| HF_HOME=/app/.hf_cache \ | |
| PORT=8000 | |
| WORKDIR /app | |
| # CPU-only torch first (avoids the multi-GB CUDA build that sentence-transformers | |
| # would otherwise pull), then the rest of the pinned requirements. | |
| COPY requirements.txt . | |
| RUN pip install --no-cache-dir torch==2.12.1 --index-url https://download.pytorch.org/whl/cpu \ | |
| && pip install --no-cache-dir -r requirements.txt | |
| # App code + shipped data artifacts (catalog.json, embeddings.npy, ids). | |
| COPY app/ ./app/ | |
| COPY data/ ./data/ | |
| # Pre-download the embedding model into the image so the first query isn't | |
| # blocked on a network fetch at runtime. | |
| RUN python -c "from sentence_transformers import SentenceTransformer; \ | |
| SentenceTransformer('all-MiniLM-L6-v2')" | |
| # The model is now baked into HF_HOME. Force offline mode so the background | |
| # warmup thread (app/main.py) never phones home to check for updates — that | |
| # was adding ~30s of avoidable network round-trips to every cold start. | |
| ENV HF_HUB_OFFLINE=1 \ | |
| TRANSFORMERS_OFFLINE=1 | |
| EXPOSE 8000 | |
| # Exec form (via sh -c for $PORT expansion) so signals reach uvicorn directly. | |
| CMD ["sh", "-c", "uvicorn app.main:app --host 0.0.0.0 --port ${PORT}"] | |