# Powerlifting Coach — web demo container. # Targets Hugging Face Spaces (Docker SDK) but runs anywhere Docker does. # # The server imports the rules engine from ../ml via app/_ml_path.py, so both # server/ and ml/ are copied in. Runtime deps live in server/pyproject.toml # (fastapi, mediapipe, opencv, numpy, anthropic); the rules engine only needs # numpy — no torch, no GPU. FROM python:3.12-slim # ffmpeg: clip normalization + browser-safe re-encode. # libgl1 / libglib2 / libgles2 / libegl1: opencv + mediapipe's GL stack. # mediapipe dlopens libGLESv2.so.2 + libEGL.so.1 at runtime, so bare libgl1 # isn't enough — without these the pipeline crashes with # "libglesv2.so.2: cannot open shared object file". RUN apt-get update && apt-get install -y --no-install-recommends \ ffmpeg \ libgl1 \ libglib2.0-0 \ libgles2 \ libegl1 \ && rm -rf /var/lib/apt/lists/* # uv — the project's package manager. COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # HF Spaces runs as a non-root user (uid 1000). Match it so writes work. RUN useradd -m -u 1000 app ENV HOME=/home/app \ UV_LINK_MODE=copy \ UV_PYTHON_DOWNLOADS=never \ PYTHONUNBUFFERED=1 WORKDIR /app COPY --chown=app:app server/ ./server/ COPY --chown=app:app ml/ ./ml/ USER app WORKDIR /app/server RUN uv sync --no-dev # HF Spaces injects $PORT (default 7860). ENV PORT=7860 EXPOSE 7860 CMD ["sh", "-c", "uv run --no-dev uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-7860}"]