PawTrace / Dockerfile
Elliott Duke
Docs: make the repo describe the system that actually shipped
79688a8
Raw
History Blame Contribute Delete
3.52 kB
# PawTrace β€” single-service image for the READ-ONLY demo (Hugging Face Spaces / any Docker host).
# Builds the React frontend, then runs the FastAPI API which also serves that frontend (one origin,
# no CORS). Bundles the fine-tuned PyTorch re-ID model (best.pt) + the HF breed classifier + the
# 1,000-dog demo database, and runs with DEMO_MODE=true so every write is blocked server-side.
# Needs ~1 GB RAM with both models loaded β€” fine on a Spaces CPU-basic (16 GB) box.
# ---- Stage 1: build the React frontend -> /web/dist ----
FROM node:20-slim AS frontend
WORKDIR /web
COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build
# ---- Stage 2: Python API (serves the built frontend) ----
FROM python:3.12-slim AS app
ENV PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
WORKDIR /app
# Base runtime deps (FastAPI, SQLAlchemy, Pillow, numpy, ...).
COPY backend/requirements-base.txt ./requirements-base.txt
RUN pip install --upgrade pip && pip install -r requirements-base.txt
# ---- REAL MATCHING (EMBEDDER=reid + BREED_CLASSIFIER=hf) ----------------------------------------
# PyTorch (CPU build) + transformers power the real re-ID embedder and breed classifier.
RUN pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu \
&& pip install "transformers>=4.40" "safetensors>=0.4"
# Pre-download the model into the image (into HF_HOME) so the first live match doesn't stall on a
# runtime download. This is a big, stable layer β€” kept cached across code changes below.
ENV HF_HOME=/app/hf_cache
RUN python -c "from transformers import AutoImageProcessor, AutoModel, AutoModelForImageClassification as M; \
k='jhoppanne/Dogs-Breed-Image-Classification-V1'; AutoImageProcessor.from_pretrained(k); \
M.from_pretrained(k); AutoModel.from_pretrained(k)"
# ------------------------------------------------------------------------------------------------
# Backend source (includes backend/demo_data/ β€” the shipped snapshot).
COPY backend/ ./
# Fine-tuned re-ID model weights (git-LFS in the Space repo) -> loaded when EMBEDDER=reid.
COPY best.pt /app/best.pt
# Geo centroid CSV lives at the repo root; copy it in and point the app at it.
COPY data/zip_centroids.csv /app/geo/zip_centroids.csv
ENV ZIP_CENTROID_FILE=/app/geo/zip_centroids.csv
# Built frontend from stage 1 (the API serves this at "/").
COPY --from=frontend /web/dist ./frontend_dist
# Bake the 1,000-dog demo snapshot (SQLite DB + processed photos) into the image's data dir, then
# drop the source copy. DEMO_MODE blocks all writes, so the DB never changes; a redeploy just
# reloads this same read-only snapshot.
RUN mkdir -p /app/data \
&& cp /app/demo_data/app.db /app/data/app.db \
&& cp -r /app/demo_data/media /app/data/media \
&& rm -rf /app/demo_data
ENV DATABASE_URL=sqlite:////app/data/app.db \
MEDIA_DIR=/app/data/media \
EMBEDDER=reid \
REID_MODEL_PATH=/app/best.pt \
REID_MODEL_VERSION=v4 \
BREED_CLASSIFIER=hf \
BREED_TOP_K=10 \
DEMO_MODE=true \
HF_HUB_OFFLINE=1 \
TRANSFORMERS_OFFLINE=1
# HF_HUB_OFFLINE/TRANSFORMERS_OFFLINE: use the model baked into HF_HOME above; never call
# huggingface.co at runtime (faster cold start, no external dependency during a demo).
# HF Spaces routes to the port declared as `app_port` in README.md (7860). Bind there; ${PORT} keeps
# it portable to hosts that inject a port (Render, etc.).
EXPOSE 7860
CMD ["sh", "-c", "uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-7860}"]