# HuggingFace Space — Unified Dockerfile # # Combines all 3 services (encoder + api + frontend) into one container. # HuggingFace Spaces only exposes port 7860 and doesn't support docker-compose. # # Architecture inside this container: # supervisord manages 3 processes: # - encoder (uvicorn on port 8001) — ONNX CLIP inference # - api (uvicorn on port 8000) — FAISS search + Whisper # - nginx (on port 7860) — serves frontend + proxies /api → 8000 # # On startup, start.sh downloads models + embeddings from HuggingFace Hub. # ── Stage 1: Build React frontend ───────────────────────────────────────── FROM node:18-alpine AS frontend-builder WORKDIR /app/frontend COPY services/frontend/package.json services/frontend/package-lock.json* ./ RUN npm ci ARG CACHEBUST=1 COPY services/frontend/ . # API is proxied via nginx at /api on port 7860 ARG VITE_API_URL="" ENV VITE_API_URL=$VITE_API_URL RUN npm run build # ── Stage 2: Main runtime image ──────────────────────────────────────────── FROM python:3.11-slim # Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ nginx \ supervisor \ ffmpeg \ git \ gcc \ g++ \ libgomp1 \ wget \ && rm -rf /var/lib/apt/lists/* # ── Install Python dependencies ──────────────────────────────────────────── COPY services/encoder/requirements.txt /tmp/encoder-requirements.txt COPY services/api/requirements.txt /tmp/api-requirements.txt RUN pip install --no-cache-dir --default-timeout=1200 \ -r /tmp/encoder-requirements.txt \ -r /tmp/api-requirements.txt \ huggingface_hub # ── Copy application code ────────────────────────────────────────────────── COPY services/encoder/main.py /app/encoder/main.py COPY services/api/main.py /app/api/main.py # ── Copy compiled frontend ───────────────────────────────────────────────── ARG CACHEBUST=1 COPY --from=frontend-builder /app/frontend/dist /usr/share/nginx/html # ── Nginx config ─────────────────────────────────────────────────────────── COPY nginx.conf /etc/nginx/conf.d/default.conf RUN rm -f /etc/nginx/sites-enabled/default # ── Supervisord config ───────────────────────────────────────────────────── COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf # ── Startup script ───────────────────────────────────────────────────────── COPY start.sh /start.sh RUN chmod +x /start.sh # ── Create required directories ──────────────────────────────────────────── RUN mkdir -p /app/models /app/embeddings /app/images /app/data /var/log/supervisor # HuggingFace Spaces runs as non-root user (uid 1000) RUN chown -R 1000:1000 /app /var/log/supervisor /var/lib/nginx /var/log/nginx \ && chmod -R 755 /app EXPOSE 7860 CMD ["/start.sh"]