# HuggingFace Spaces Dockerfile — CPU-only, port 7860 # Follows HF recommended pattern: USER user before pip installs (no chown needed) FROM python:3.10-slim # ── System dependencies (run as root) ───────────────────────────────────────── RUN apt-get update && apt-get install -y --no-install-recommends \ ffmpeg \ tesseract-ocr \ tesseract-ocr-eng \ libsndfile1 \ poppler-utils \ libgomp1 \ libglib2.0-0 \ libsm6 \ libxext6 \ libxrender1 \ build-essential \ python3-dev \ git \ curl \ && rm -rf /var/lib/apt/lists/* # ── Create non-root user required by HuggingFace Spaces (UID 1000) ──────────── RUN useradd -m -u 1000 user # ── Switch to non-root user for ALL subsequent steps ────────────────────────── # This is HF's recommended pattern — installs go to ~/.local, no chown needed USER user # ── Environment variables ────────────────────────────────────────────────────── ENV HOME=/home/user \ PATH=/home/user/.local/bin:$PATH \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ TRANSFORMERS_CACHE=/home/user/.cache/huggingface \ HF_HOME=/home/user/.cache/huggingface \ TORCH_HOME=/home/user/.cache/torch \ NLTK_DATA=/home/user/nltk_data \ API_PORT=7860 \ API_HOST=0.0.0.0 \ ENABLE_GPU=false \ ENABLE_REDIS=false \ DEFAULT_WHISPER_MODEL=base \ ENABLE_QUALITY_ASSESSMENT=false \ ENABLE_BACKTRANSLATION_CHECK=false \ ENABLE_ENSEMBLE=false \ MAX_WORKERS=1 \ BATCH_SIZE=8 \ ENVIRONMENT=production \ CORS_ORIGINS='["*"]' \ LOG_LEVEL=INFO # ── Working directory ────────────────────────────────────────────────────────── WORKDIR /home/user/app # ── Upgrade pip and build tools ──────────────────────────────────────────────── RUN pip install --no-cache-dir --upgrade pip setuptools wheel # ── Install CPU-only PyTorch (separate layer for caching) ───────────────────── RUN pip install --no-cache-dir \ torch==2.1.1+cpu \ torchaudio==2.1.1+cpu \ --index-url https://download.pytorch.org/whl/cpu # ── Install app dependencies ─────────────────────────────────────────────────── # requirements.txt is renamed from requirements.spaces.txt by deploy_hf.sh # # --no-build-isolation: pip normally creates an isolated sandbox to build source # distributions (packages with no pre-built wheel, like openai-whisper and # sacremoses). That sandbox does NOT inherit our installed setuptools, so # pkg_resources is missing and the build fails. This flag tells pip to build # packages using the current environment where setuptools is already present. COPY --chown=user:user requirements.txt . RUN pip install --no-cache-dir --no-build-isolation -r requirements.txt # ── Create runtime directories ───────────────────────────────────────────────── RUN mkdir -p \ /home/user/app/uploads \ /home/user/app/temp \ /home/user/app/cache \ /home/user/app/logs \ /home/user/app/models \ /home/user/.cache/huggingface \ /home/user/.cache/torch \ /home/user/.cache/whisper \ /home/user/nltk_data # ── NLTK data (~3 MB, safe at build time) ───────────────────────────────────── RUN python -c "\ import nltk; \ nltk.download('punkt', download_dir='/home/user/nltk_data', quiet=True); \ nltk.download('punkt_tab', download_dir='/home/user/nltk_data', quiet=True); \ nltk.download('stopwords', download_dir='/home/user/nltk_data', quiet=True)" # ── NOTE: ML models (NLLB-200 ~2.5 GB, Whisper base ~150 MB) are NOT downloaded # here because the Docker BUILD environment has limited RAM and OOMKills on model # loading. Models are downloaded automatically on first startup by the app's # lifespan handler (main.py) in the RUNNING container which has 16 GB RAM. # ── Copy application code ────────────────────────────────────────────────────── COPY --chown=user:user . . RUN rm -f .env .env.spaces* 2>/dev/null || true # ── Expose HF Spaces port ────────────────────────────────────────────────────── EXPOSE 7860 HEALTHCHECK --interval=30s --timeout=15s --start-period=120s --retries=3 \ CMD curl -f http://localhost:7860/health || exit 1 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]