Spaces:
Sleeping
Sleeping
| # Calculus Animator โ Hugging Face Space (Docker SDK) image. | |
| # | |
| # Single-stage build: FastAPI process serves the static ``ui/`` bundle at | |
| # ``/`` and the ``/api/*`` JSON shim that mirrors ``api.bridge.CalculusAPI`` | |
| # for the browser-side ``space_bridge.js``. | |
| # | |
| # Slide-render note: SDL2 runtime libs are installed below so a future | |
| # ``pygame==โฆ`` line drop-in to ``requirements.txt`` enables the slide | |
| # render endpoints without rebuilding the OS layer. v1 ships without | |
| # pygame; ``/api/render_learning_slide`` returns ModuleNotFoundError via | |
| # the global error envelope until that line lands. | |
| FROM python:3.11-slim AS base | |
| # โโ OS deps โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # xvfb + libsdl2-* + fontconfig: pygame runtime support (headless rendering | |
| # under SDL_VIDEODRIVER=dummy). Layered first so the Python install layer | |
| # below stays cache-friendly across requirements.txt edits. | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| xvfb \ | |
| libsdl2-2.0-0 \ | |
| libsdl2-image-2.0-0 \ | |
| libsdl2-mixer-2.0-0 \ | |
| libsdl2-ttf-2.0-0 \ | |
| fontconfig \ | |
| fonts-dejavu \ | |
| ca-certificates \ | |
| && rm -rf /var/lib/apt/lists/* | |
| # Headless SDL: pygame opens a dummy framebuffer, never touches a GPU/X server. | |
| ENV SDL_VIDEODRIVER=dummy \ | |
| PYGAME_HIDE_SUPPORT_PROMPT=1 \ | |
| XDG_RUNTIME_DIR=/tmp \ | |
| PYTHONDONTWRITEBYTECODE=1 \ | |
| PYTHONUNBUFFERED=1 \ | |
| PIP_NO_CACHE_DIR=1 \ | |
| PIP_DISABLE_PIP_VERSION_CHECK=1 | |
| WORKDIR /app | |
| # โโ Python deps โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # Copy requirements first so the install layer caches across source edits. | |
| # We intentionally skip ``requirements-ai.txt`` (chromadb + sentence-transformers | |
| # are heavyweight and unused by the desktop core that the Space serves); | |
| # adding them is a one-line ``-r requirements-ai.txt`` change in this RUN. | |
| COPY requirements.txt ./ | |
| RUN pip install --upgrade pip \ | |
| && pip install -r requirements.txt | |
| # โโ Source โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # Copy the runtime trees the FastAPI app actually imports; release-only | |
| # scripts and dev fixtures stay out of the image. | |
| COPY ai_tutor/ ./ai_tutor/ | |
| COPY api/ ./api/ | |
| COPY core/ ./core/ | |
| COPY ui/ ./ui/ | |
| COPY slide_renderer/ ./slide_renderer/ | |
| COPY scripts/ ./scripts/ | |
| COPY data/ ./data/ | |
| # ``assets/`` (pygame fonts) is intentionally absent on this branch โ HF's | |
| # binary-file rule rejects ``.ttf`` files, and slide rendering is not the | |
| # Space's primary surface. ``/api/render_learning_slide`` will surface a | |
| # missing-font error via the structured error envelope; Solve and graph | |
| # endpoints work without it. Restore via Git LFS if slide rendering is | |
| # wanted on the Space. | |
| # ``config.py`` lives at the project root and is imported by ``run.py`` and | |
| # tests; keep it on the image so any module that walks ``sys.path[0]`` | |
| # resolves it the same way as on the host. | |
| COPY config.py ./config.py | |
| # โโ Non-root runtime โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # Hugging Face Spaces require the container to run as a non-root user (UID | |
| # 1000 is the convention HF documents). Create the user, hand it ownership of | |
| # /app, and switch. | |
| RUN useradd --create-home --uid 1000 appuser \ | |
| && chown -R appuser:appuser /app | |
| USER appuser | |
| EXPOSE 7860 | |
| # ``--host 0.0.0.0`` is required for HF Spaces (host can only route to the | |
| # container via the published port). Loopback-only binding lives on the | |
| # desktop branch's ``run.py`` path; this image's threat model is the | |
| # Space-managed reverse proxy in front of the container. | |
| CMD ["uvicorn", "ai_tutor.main:app", "--host", "0.0.0.0", "--port", "7860"] | |