# Dockerfile — Enterprise Lens V4 FROM python:3.10-slim # ── HF_TOKEN — must be declared immediately after FROM ────────── # ARG before any RUN step so HF Spaces build secrets are available. ARG HF_TOKEN="" ENV HF_TOKEN=${HF_TOKEN} WORKDIR /app # ── System deps ─────────────────────────────────────────────────── # g++ / build-essential : required to compile insightface C++ extensions # libgl1 + libglib2.0-0 : OpenCV headless # libgomp1 : OpenMP for ONNX runtime # git + curl : HF hub downloads RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ g++ \ libgl1 \ libglib2.0-0 \ libgomp1 \ git \ curl \ && rm -rf /var/lib/apt/lists/* # ── Python deps ─────────────────────────────────────────────────── COPY requirements.txt . RUN pip install --no-cache-dir --compile -r requirements.txt # ── Copy application code ───────────────────────────────────────── COPY . . RUN mkdir -p temp_uploads saved_images && chmod -R 777 temp_uploads saved_images # ── Pre-download public models at BUILD time ────────────────────── RUN python - <<'EOF' import os, sys print("Pre-downloading SigLIP...") from transformers import AutoProcessor, AutoModel, AutoImageProcessor AutoProcessor.from_pretrained("google/siglip-base-patch16-224", use_fast=True) AutoModel.from_pretrained("google/siglip-base-patch16-224") print("SigLIP done") print("Pre-downloading DINOv2...") AutoImageProcessor.from_pretrained("facebook/dinov2-base") AutoModel.from_pretrained("facebook/dinov2-base") print("DINOv2 done") print("Pre-downloading YOLO11n-seg...") from ultralytics import YOLO YOLO("yolo11n-seg.pt") print("YOLO done") print("Pre-downloading InsightFace buffalo_l...") import numpy as np from insightface.app import FaceAnalysis face_app = FaceAnalysis(name="buffalo_l", providers=["CPUExecutionProvider"]) face_app.prepare(ctx_id=-1, det_size=(640, 640)) face_app.get(np.zeros((112, 112, 3), dtype=np.uint8)) print("InsightFace buffalo_l done") print("All public models pre-downloaded successfully") EOF # ── Pre-download AdaFace (graceful — never fails the build) ─────── RUN python - <<'EOF' import os, sys, traceback HF_TOKEN = os.getenv("HF_TOKEN", "").strip() REPO_ID = "minchul/cvlface_adaface_ir50_ms1mv2" CACHE_PATH = os.path.expanduser("~/.cvlface_cache/minchul/cvlface_adaface_ir50_ms1mv2") if not HF_TOKEN: print("HF_TOKEN not set - skipping AdaFace pre-download") print("Fallback: ArcFace zero-padded to 1024-D (build succeeds)") sys.exit(0) try: from huggingface_hub import hf_hub_download from transformers import AutoModel import torch print("Pre-downloading AdaFace IR-50 MS1MV2...") os.makedirs(CACHE_PATH, exist_ok=True) hf_hub_download(repo_id=REPO_ID, filename="files.txt", token=HF_TOKEN, local_dir=CACHE_PATH, local_dir_use_symlinks=False) with open(os.path.join(CACHE_PATH, "files.txt")) as f: extra = [x.strip() for x in f.read().split("\n") if x.strip()] for fname in extra + ["config.json", "wrapper.py", "model.safetensors"]: fpath = os.path.join(CACHE_PATH, fname) if not os.path.exists(fpath): print("Downloading " + fname) hf_hub_download(repo_id=REPO_ID, filename=fname, token=HF_TOKEN, local_dir=CACHE_PATH, local_dir_use_symlinks=False) cwd = os.getcwd() os.chdir(CACHE_PATH) sys.path.insert(0, CACHE_PATH) try: model = AutoModel.from_pretrained( CACHE_PATH, trust_remote_code=True, token=HF_TOKEN) finally: os.chdir(cwd) if CACHE_PATH in sys.path: sys.path.remove(CACHE_PATH) with torch.no_grad(): out = model(torch.zeros(1, 3, 112, 112)) emb = out if isinstance(out, torch.Tensor) else out.embedding print("AdaFace done - output dim=" + str(emb.shape[-1])) except Exception as e: print("AdaFace pre-download failed: " + str(e)) print(traceback.format_exc()[-400:]) print("Build continues - ArcFace-only fallback active") sys.exit(0) EOF RUN pip install --no-cache-dir omegaconf EXPOSE 7860 ENV WEB_CONCURRENCY=1 CMD uvicorn main:app \ --host 0.0.0.0 \ --port 7860 \ --workers ${WEB_CONCURRENCY} \ --timeout-keep-alive 75