FROM python:3.11-slim LABEL maintainer="local-llm-api" LABEL description="Local LLM inference API — llama-cpp-python + Flask (multi-model)" WORKDIR /app # ── System deps ─────────────────────────────────────────────────────────────── RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ ca-certificates \ build-essential \ && rm -rf /var/lib/apt/lists/* # ── Copy project files ──────────────────────────────────────────────────────── COPY . . RUN chmod +x install.sh start.sh # ── Environment ─────────────────────────────────────────────────────────────── # PORT=7860 for HuggingFace Spaces. Override at runtime for other hosts. # Set ACTIVE_MODELS to control which models load (comma-separated names). # Example: docker run -e ACTIVE_MODELS="Qwen3.5-4B,DeepSeek-R1-8B" ... ENV PORT=7860 ENV PYTHONUNBUFFERED=1 # ── Python deps ─────────────────────────────────────────────────────────────── # Install llama-cpp-python from CPU wheel index first; fall back to PyPI build. RUN pip install --no-cache-dir \ flask \ huggingface-hub \ numpy \ chromadb \ sentence-transformers \ && ( pip install --no-cache-dir llama-cpp-python \ --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cpu \ || pip install --no-cache-dir llama-cpp-python ) # ── Override port for HuggingFace Spaces (7860 instead of 5000) ────────────── #RUN python3 -c " #import json #with open('install.json') as f: c = json.load(f) #c.setdefault('server', {})['port'] = 7860 #with open('install.json', 'w') as f: json.dump(c, f, indent=2) #" # ── Model volume ────────────────────────────────────────────────────────────── # Mount models here at runtime: # docker run -v /host/models:/app/model ... # Each model lives in /app/model//chunks/*.gguf VOLUME ["/app/model"] # ── Port ───────────────────────────────────────────────────────────────────── EXPOSE 7860 # ── Health check ────────────────────────────────────────────────────────────── # Generous start-period — models can take 1-5 min to join+load from disk. HEALTHCHECK --interval=30s --timeout=15s --start-period=600s --retries=10 \ CMD curl -sf "http://localhost:${PORT}/health" | python3 -c \ "import sys,json; d=json.load(sys.stdin); sys.exit(0 if d.get('status') in ('ok','partial') else 1)" \ || exit 1 # ── Entrypoint ──────────────────────────────────────────────────────────────── # start.sh: installs any missing packages, syncs/downloads models, starts Flask. CMD ["bash", "start.sh"]