# syntax=docker/dockerfile:1.7 FROM python:3.12-slim ENV PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ UV_LINK_MODE=copy \ UV_NO_SYNC_PROGRESS=1 \ UV_COMPILE_BYTECODE=1 \ PORT=8000 RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ curl ca-certificates \ imagemagick \ ghostscript \ fonts-dejavu \ pdf2svg \ texlive \ texlive-latex-extra \ texlive-pictures \ texlive-science \ && rm -rf /var/lib/apt/lists/* # Install uv COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # Change the working directory to the `app` directory WORKDIR /app # Install dependencies first (better cache hit) RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock,readwrite \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml,readwrite \ uv sync --locked --no-install-project # Add latex safety features # Hardening TeXLive configuration for security # 1. Disable shell_escape (prevents \write18 execution of arbitrary shell commands) # 2. Set openout/openin to paranoid (prevents reading/writing files outside working dir like /etc/passwd) # 3. Disable parse_first_line (prevents passing arguments via source file comments) RUN echo "shell_escape = f" >> /etc/texmf/web2c/texmf.cnf && \ echo "openout_any = p" >> /etc/texmf/web2c/texmf.cnf && \ echo "openin_any = p" >> /etc/texmf/web2c/texmf.cnf && \ echo "parse_first_line = f" >> /etc/texmf/web2c/texmf.cnf # Copy the project into the image COPY . /app # Sync the project RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --locked ENV PATH="/app/.venv/bin:${PATH}" EXPOSE 8000 CMD ["uv", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]