# syntax=docker/dockerfile:1 # --------------------------------------------------------------------------- # Production image for the Document-Agent FastAPI backend. # # It bundles Docling + (CPU) torch + the layout/table/OCR models so the # container is self-contained: no model downloads at runtime, fast cold start, # works offline. On Linux the HuggingFace symlink cache works normally, so the # Windows WinError-1314 issue does not apply here. # --------------------------------------------------------------------------- FROM python:3.12-slim ENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 \ HF_HUB_DISABLE_SYMLINKS_WARNING=1 \ # Fixed, shared cache locations so the non-root runtime user finds the # models baked in during build. HF_HOME=/opt/models/hf \ EASYOCR_MODULE_PATH=/opt/models/easyocr \ TORCH_HOME=/opt/models/torch \ DATA_DIR=/data # Native libs needed by docling / opencv / easyocr. RUN apt-get update && apt-get install -y --no-install-recommends \ libgl1 \ libglib2.0-0 \ libgomp1 \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # Install CPU-only torch/torchvision FIRST so docling's torch dependency # resolves to the lightweight CPU wheels instead of multi-GB CUDA builds. RUN pip install --index-url https://download.pytorch.org/whl/cpu \ torch torchvision COPY requirements.txt . RUN pip install -r requirements.txt # Bake the models into the image. COPY scripts/prefetch_models.py scripts/prefetch_models.py RUN mkdir -p /opt/models && python scripts/prefetch_models.py # App source. COPY . . # Run as a non-root user; /data holds uploads, sqlite db and rendered pages and # is expected to be a mounted persistent volume in production. RUN useradd --create-home app \ && mkdir -p /data \ && chown -R app:app /data /app /opt/models USER app EXPOSE 8000 # Honour $PORT (Render/most PaaS inject it); default 8000 for local/compose. HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \ CMD python -c "import os,urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://localhost:%s/api/health' % os.environ.get('PORT','8000')).status==200 else 1)" CMD ["sh", "-c", "uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-8000}"]