# Single-container Hugging Face Space image for 9XAIPal. # The container starts PostgreSQL (with pgvector) + Redis in the background and # then launches the plain FastAPI app (app.py) on port 7860 via supervisord. # Pin to Debian bookworm: the PGDG apt repo below targets bookworm, and the # default python:3.11-slim now resolves to Debian trixie (libicu76/libldap-2.6), # whose libs can't satisfy the bookworm PostgreSQL packages. FROM python:3.11-slim-bookworm ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ # Tell uvicorn to bind on 0.0.0.0 by default. HOST=0.0.0.0 \ PORT=7860 \ # Default paths inside the container. UI_DIR=/code/dist \ # In-container Ollama (embeddings only): bind locally and store the baked # model where both build-time pull and runtime serve will look for it. OLLAMA_HOST=127.0.0.1:11434 \ OLLAMA_MODELS=/root/.ollama/models \ # The Space image does not bake MinerU (several GB). Enable the PyMuPDF # text-only fallback so uploads still process out of the box; install MinerU # and set this to 0 for higher-fidelity extraction. ALLOW_PYMUPDF_FALLBACK=1 WORKDIR /code # Install Redis, PostgreSQL 16 + pgvector, and basic build tooling. # - Redis is required by the backend Celery queue. # - PostgreSQL (with the pgvector extension) is the app's primary database; # it runs inside this container and is created/initialized by start.sh. # - build-essential/libpq-dev are here in case a dependency wheel is # unavailable for the current platform. # PostgreSQL + pgvector come from the official PGDG apt repository. RUN apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates curl gnupg \ zstd \ redis-server \ supervisor \ build-essential \ libpq-dev \ && install -d /usr/share/postgresql-common/pgdg \ && curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \ -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \ && echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \ > /etc/apt/sources.list.d/pgdg.list \ && apt-get update \ && apt-get install -y --no-install-recommends \ postgresql-16 \ postgresql-16-pgvector \ && rm -rf /var/lib/apt/lists/* # Install Ollama and bake the embedding model into the image. Chat runs on # Ollama Cloud (a 31B model), but the cloud doesn't host embedding models, so we # serve qwen3-embedding from an in-container Ollama at localhost:11434. Pulling # the weights at build time bakes them into an image layer, so cold starts don't # re-download ~640 MB and the Space works even without a persistent disk. RUN curl -fsSL https://ollama.com/install.sh | sh \ && (ollama serve & srv=$!; \ for i in $(seq 1 30); do ollama list >/dev/null 2>&1 && break; sleep 1; done; \ ollama pull qwen3-embedding; \ kill "$srv" 2>/dev/null || true) # Install Python dependencies first so layer caching works across code changes. COPY requirements.txt . RUN pip install --no-cache-dir --upgrade pip \ && pip install --no-cache-dir -r requirements.txt # Copy the rest of the project (backend code, tests, and the React dist build). COPY . . COPY supervisord.conf /code/supervisord.conf RUN chmod +x /code/start.sh EXPOSE 7860 # Docker will restart the container if /healthz starts returning unhealthy. # start.sh brings up PostgreSQL (+pgvector), Redis and Ollama, then supervisord # keeps the API + Celery worker alive. HEALTHCHECK --interval=30s --timeout=15s --start-period=120s --retries=4 \ CMD curl -fsS http://127.0.0.1:7860/healthz >/dev/null || exit 1 CMD ["bash", "/code/start.sh"]