Sanket-Setu / Dockerfile
devrajsinh2012's picture
feat: serve full-stack app from single HF Space container
537f246
# ─────────────────────────────────────────────────────────────────────────────
# SanketSetu β€” Dockerfile (full-stack: React frontend + FastAPI backend)
# Build context: repo root (SanketSetu/)
#
# docker build -t sanketsetu .
# docker run -p 7860:7860 sanketsetu
# ─────────────────────────────────────────────────────────────────────────────
# ── Stage 1: Build React frontend ────────────────────────────────────────────
FROM node:20-slim AS frontend-builder
WORKDIR /frontend
COPY frontend/package.json frontend/package-lock.json* ./
RUN npm ci --prefer-offline
COPY frontend/ ./
# No VITE_WS_URL β€” the hook derives it from window.location at runtime
RUN npm run build
# ── Stage 2: Python backend ───────────────────────────────────────────────────
FROM python:3.12-slim AS base
# System libraries needed by OpenCV headless + Pillow
RUN apt-get update && apt-get install -y --no-install-recommends \
libgl1 libglib2.0-0 libgomp1 \
&& rm -rf /var/lib/apt/lists/*
# ── Python dependencies (cached layer) ───────────────────────────────────────
WORKDIR /app
COPY backend/requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
# ── Application source ────────────────────────────────────────────────────────
COPY backend/app/ ./app/
# ── Frontend static files (built in Stage 1) ─────────────────────────────────
COPY --from=frontend-builder /frontend/dist ./static/
# ── Model artefacts ───────────────────────────────────────────────────────────
# Copied to /models so the container is fully self-contained.
# Override at runtime with -e WEIGHTS_DIR=/mnt/models + bind-mount if preferred.
COPY Mediapipe_XGBoost/ /models/Mediapipe_XGBoost/
COPY CNN_Autoencoder_LightGBM/ /models/CNN_Autoencoder_LightGBM/
COPY CNN_PreTrained/ /models/CNN_PreTrained/
# ── Runtime environment ───────────────────────────────────────────────────────
# PORT=7860 is the Hugging Face Spaces default; override with -e PORT=xxxx if needed.
ENV WEIGHTS_DIR=/models \
PORT=7860 \
KERAS_BACKEND=tensorflow \
TF_CPP_MIN_LOG_LEVEL=3 \
CUDA_VISIBLE_DEVICES="" \
TF_ENABLE_ONEDNN_OPTS=0 \
OMP_NUM_THREADS=4 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
EXPOSE 7860
# ── Health-check ──────────────────────────────────────────────────────────────
# Wait up to 3 minutes for models to load before marking the container healthy.
HEALTHCHECK --interval=30s --timeout=10s --start-period=180s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:${PORT}/health', timeout=5)"
CMD uvicorn app.main:app --host 0.0.0.0 --port ${PORT}