shl-recommender / Dockerfile
Eshit's picture
HF Space deploy snapshot
5733f37
Raw
History Blame Contribute Delete
1.61 kB
# 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}"]