media-analyzer / Dockerfile
nxj18
Retune for L40S (48GB): CUDA graphs back on, roomier memory split
3469a45
Raw
History Blame Contribute Delete
3.84 kB
# media-analyzer: JoyCaption (via vLLM, OpenAI-compatible) + GPU face
# detection/embedding (InsightFace buffalo_l on onnxruntime-gpu), fronted by
# one FastAPI gateway owning bearer auth and instrumentation.
#
# Patterns follow ~/huggingface-engines (tts-dialogue-engine-moss), the
# proven docker-Space template: uid-1000 user (HF chowns /data to 1000),
# HF_HOME on LOCAL disk (mmap from the network-backed /data volume hangs
# mid-load), PYTHONUNBUFFERED, app_port 7860.
#
# Base: the official vLLM image β€” its torch/vllm/CUDA/cuDNN are aligned,
# which is exactly the versioning we don't want to hand-roll. onnxruntime-gpu
# >=1.19 targets the same CUDA 12 / cuDNN 9 family.
FROM vllm/vllm-openai:latest
RUN apt-get update && apt-get install -y --no-install-recommends \
unzip curl \
&& rm -rf /var/lib/apt/lists/*
# The vllm image's python is pip-managed; PIP_BREAK_SYSTEM_PACKAGES covers
# newer Debian/Ubuntu externally-managed setups either way.
ENV PIP_BREAK_SYSTEM_PACKAGES=1
# insightface depends on plain `onnxruntime` (the CPU wheel), and both ORT
# packages unpack into the SAME `onnxruntime` module directory β€” whichever
# installs last wins file-by-file. So: install insightface (and friends)
# first, then purge every ORT flavor, then force-reinstall the GPU wheel
# LAST so all module files belong to it.
RUN pip install --no-cache-dir \
insightface \
"fastapi>=0.115" \
"uvicorn>=0.30" \
"httpx>=0.27" \
opencv-python-headless \
hf_transfer
RUN pip uninstall -y onnxruntime onnxruntime-gpu 2>/dev/null || true
RUN pip install --no-cache-dir --force-reinstall --no-deps onnxruntime-gpu \
# numpy/protobuf etc. are already present via insightface; --no-deps keeps
# this step from dragging anything else in. Then PROVE the CUDA provider
# is at least available in the installed package at build time.
&& python3 -c "import onnxruntime as ort; assert 'CUDAExecutionProvider' in ort.get_available_providers(), ort.get_available_providers()"
# Pre-bake buffalo_l (SCRFD detector + ArcFace w600k) so the face endpoint is
# ready at container start. FaceAnalysis(root=/opt/insightface) resolves
# {root}/models/buffalo_l.
RUN mkdir -p /opt/insightface/models/buffalo_l \
&& curl -L -o /tmp/buffalo_l.zip \
https://github.com/deepinsight/insightface/releases/download/v0.7/buffalo_l.zip \
&& unzip -o /tmp/buffalo_l.zip -d /opt/insightface/models/buffalo_l \
&& rm /tmp/buffalo_l.zip \
# fail the BUILD if the zip layout ever changes β€” a missing file here
# would otherwise surface as a runtime re-download attempt into a
# read-only path
&& test -f /opt/insightface/models/buffalo_l/det_10g.onnx \
&& test -f /opt/insightface/models/buffalo_l/w600k_r50.onnx \
&& chmod -R a+rX /opt/insightface
# Claim uid 1000 β€” the uid HF Spaces chowns the persistent /data volume to.
RUN userdel -r ubuntu 2>/dev/null || true \
&& useradd -m -u 1000 user
WORKDIR /app
COPY gateway.py start.sh ./
RUN chmod +x start.sh && chown -R user:user /app
USER user
# Reduce VRAM fragmentation (set before CUDA init). vLLM and the ONNX face
# session share the GPU; vLLM's slice is bounded by GPU_MEM_UTIL below.
ENV PYTORCH_CUDA_ALLOC_CONF="expandable_segments:True"
ENV PYTHONUNBUFFERED=1
# HF_HOME must be LOCAL disk (weights are mmap'd from here). If the Space has
# persistent storage, start.sh restores a previously saved cache from
# HF_PERSIST_DIR before downloading.
ENV HF_HOME=/app/.hf-cache \
HF_PERSIST_DIR=/model-storage/huggingface \
HF_HUB_ENABLE_HF_TRANSFER=1 \
MODEL_ID=fancyfeast/llama-joycaption-beta-one-hf-llava \
SERVED_MODEL_NAME=joycaption-beta-one \
VLLM_PORT=8001 \
GPU_MEM_UTIL=0.85 \
VLLM_ENFORCE_EAGER=0 \
MAX_MODEL_LEN=4096 \
PORT=7860
EXPOSE 7860
ENTRYPOINT ["./start.sh"]