# CUDA + cuDNN + Python base. Matches A10 (Ampere) on HF Spaces. FROM nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04 ENV DEBIAN_FRONTEND=noninteractive \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 # System deps marker-pdf needs at runtime: poppler for PDF rendering, plus the # usual fonts so rasterized output looks right. ca-certs for outbound HTTPS. RUN apt-get update && apt-get install -y --no-install-recommends \ python3.11 python3.11-venv python3-pip \ git \ poppler-utils \ libgl1 libglib2.0-0 \ fonts-liberation fonts-dejavu-core \ ca-certificates \ curl \ && rm -rf /var/lib/apt/lists/* RUN ln -sf /usr/bin/python3.11 /usr/local/bin/python && \ ln -sf /usr/bin/python3.11 /usr/local/bin/python3 # HF Spaces runs containers as a non-root user (UID 1000) by default. Create # matching user so files we write at runtime have sane ownership. RUN useradd -m -u 1000 -s /bin/bash app # Pin every cache marker touches to /data (HF Bucket mount). Without this, # cold starts re-download multiple GB of weights even though the bucket is # attached: # HF_HOME / HF_HUB_CACHE / TRANSFORMERS_CACHE — HuggingFace Hub model cache. # TORCH_HOME — Torch hub checkpoints. # XDG_CACHE_HOME — catches anything that writes to `~/.cache/...` (e.g. # datalab's text-detection + OCR-error-detection models, which marker # pulls separately from the Hub). # DATALAB_CACHE_DIR — explicit datalab override, belt-and-suspenders. ENV HF_HOME=/data/hf \ HF_HUB_CACHE=/data/hf/hub \ TRANSFORMERS_CACHE=/data/hf/transformers \ TORCH_HOME=/data/torch \ XDG_CACHE_HOME=/data/cache \ DATALAB_CACHE_DIR=/data/datalab \ PORT=7860 WORKDIR /app COPY --chown=app:app requirements.txt /app/requirements.txt RUN pip install --upgrade pip && pip install -r /app/requirements.txt # marker-pdf calls download_font() during PdfConverter init, which writes to # `/static/fonts/`. That dir doesn't exist yet and the app user # can't create it under root-owned site-packages. Pre-create + chown so marker # can populate it on first parse. # # Use `pip show` to derive the install location — robust against the python3 # / python3.10 / python3.11 split on this image (apt installs 3.11 but pip # is bound to 3.10 where marker actually lives). RUN STATIC_DIR="$(pip show marker-pdf | awk -F': ' '/^Location:/ {print $2 "/static"}')" \ && mkdir -p "$STATIC_DIR/fonts" \ && chown -R app:app "$STATIC_DIR" COPY --chown=app:app app /app/app USER app EXPOSE 7860 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860", "--timeout-keep-alive", "1800"]