# syntax=docker/dockerfile:1 # Hugging Face Docker Spaces expects a single container listening on app_port # (7860 by default). This Dockerfile builds the Vite frontend and serves it # from the FastAPI backend on port 7860. FROM node:20-alpine AS frontend-build WORKDIR /frontend # Install deps with cache-friendly layers COPY frontend/package.json frontend/package-lock.json ./ RUN npm ci # Build frontend COPY frontend/ ./ # When the frontend is served by the same FastAPI origin, use relative /api. ENV VITE_API_URL= RUN npm run build FROM python:3.11-slim-bookworm AS runtime WORKDIR /app ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 \ PORT=7860 # System deps for PaddleOCR, PDF processing, and healthcheck RUN set -eux; \ if [ -f /etc/apt/sources.list ]; then sed -i 's|http://|https://|g' /etc/apt/sources.list; fi; \ if [ -f /etc/apt/sources.list.d/debian.sources ]; then sed -i 's|http://|https://|g' /etc/apt/sources.list.d/debian.sources; fi; \ apt-get -o Acquire::Retries=3 update; \ apt-get install -y --no-install-recommends \ libgl1 \ libglib2.0-0 \ libsm6 \ libxrender1 \ libxext6 \ libgomp1 \ ca-certificates \ curl \ zstd \ poppler-utils \ ; \ rm -rf /var/lib/apt/lists/* # Ollama server (runs locally inside the container) # Use the official Linux tarball (the previous direct binary URL may 404). RUN set -eux; \ curl -fsSL "https://ollama.com/download/ollama-linux-amd64.tar.zst" \ | tar -I zstd -x -C /usr; \ command -v ollama; \ ollama --version || true # Create persistent data directory for SQLite, uploads, and Ollama model cache # Hugging Face Spaces mounts /data as persistent storage RUN mkdir -p /data /data/uploads /data/chroma_db /data/ollama_models && chmod -R 777 /data # Python deps COPY backend/requirements.txt ./requirements.txt RUN python -m pip install --no-cache-dir -r requirements.txt # Backend code (puts /app/app on PYTHONPATH) COPY backend/ ./ # Frontend production build served by FastAPI COPY --from=frontend-build /frontend/dist /app/frontend_dist # Environment variables for HF Spaces ENV FRONTEND_DIST_DIR=/app/frontend_dist \ DATABASE_URL="sqlite+aiosqlite:////data/lumea.db" \ CHROMA_PERSIST_DIR="/data/chroma_db" \ UPLOAD_DIR="/data/uploads" \ OLLAMA_BASE_URL="http://127.0.0.1:11434" \ OLLAMA_MODEL="hf.co/unsloth/medgemma-4b-it-GGUF:Q6_K_XL" \ OLLAMA_MODELS="/data/ollama_models" \ OLLAMA_PULL_ON_START="true" # Create a startup script that ensures directories exist, starts Ollama, then runs the API. # We keep the model cache in /data so it persists across HF Space restarts. RUN printf '#!/bin/sh\nset -eu\n\nmkdir -p /data /data/uploads /data/chroma_db \"$OLLAMA_MODELS\" 2>/dev/null || true\n\n# Start Ollama server in background\nollama serve >/tmp/ollama.log 2>&1 &\n\n# Best-effort warm pull (first start will download; subsequent starts are fast)\nif [ \"${OLLAMA_PULL_ON_START:-true}\" = \"true\" ] && [ -n \"${OLLAMA_MODEL:-}\" ]; then\n (ollama pull \"$OLLAMA_MODEL\" >/tmp/ollama-pull.log 2>&1 || true) &\nfi\n\nexec uvicorn app.main:app --host 0.0.0.0 --port 7860\n' > /app/start.sh && chmod +x /app/start.sh EXPOSE 7860 HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ CMD curl -f http://localhost:7860/api || exit 1 CMD ["/app/start.sh"]