File size: 3,437 Bytes
419099f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dabd3c3
419099f
10562a9
2d21c4c
419099f
 
 
dabd3c3
10562a9
dabd3c3
10562a9
 
 
 
dabd3c3
 
2d21c4c
dabd3c3
2d21c4c
419099f
 
 
 
 
 
 
 
 
2d21c4c
 
 
 
 
dabd3c3
 
c20605a
dabd3c3
 
2d21c4c
dabd3c3
 
 
419099f
 
 
2d21c4c
419099f
 
2d21c4c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 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"]