| FROM python:3.12-slim | |
| # Non-root user (HF Spaces convention; writable HOME for the HF cache the model | |
| # is pulled into at boot). | |
| # GLINER_MOCK=0: the deployed Space runs live inference (the local dev kit | |
| # defaults to mock; the env var flips only this image). | |
| RUN useradd -m -u 1000 user | |
| USER user | |
| ENV HOME=/home/user \ | |
| PATH=/home/user/.local/bin:$PATH \ | |
| HF_HOME=/home/user/.cache/huggingface \ | |
| PYTHONUNBUFFERED=1 \ | |
| GLINER_MOCK=0 | |
| WORKDIR /home/user/app | |
| # git needed to pip-install gliner2 from GitHub branch | |
| USER root | |
| RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/* | |
| USER user | |
| # CPU-only torch (default PyPI wheel is CUDA and huge). Only needed for the real | |
| # model; the mock path works on flask alone. | |
| RUN pip install --no-cache-dir --user torch --index-url https://download.pytorch.org/whl/cpu | |
| RUN pip install --no-cache-dir --user flask gunicorn protobuf | |
| # GLiNER2 from main branch (required for boundary architecture support) | |
| RUN pip install --no-cache-dir --user "gliner2[local] @ git+https://github.com/fastino-ai/GLiNER2.git@main" | |
| COPY --chown=user . . | |
| # Pre-download model at build time to speed up cold starts. The model repo is | |
| # public on the HF hub, so no token is needed. | |
| RUN python -c "from huggingface_hub import snapshot_download; snapshot_download('fastino/gliner2.5-multi-v1')" || echo "model pre-download skipped" | |
| EXPOSE 7860 | |
| # One worker (single shared model), threads for static/infer connections. | |
| # No --preload: avoids the torch/OpenMP fork-after-threads deadlock. | |
| CMD ["gunicorn", "-w", "1", "--threads", "8", "-k", "gthread", "-b", "0.0.0.0:7860", "--timeout", "0", "app:app"] | |