FROM python:3.11-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ffmpeg \ build-essential \ git \ && rm -rf /var/lib/apt/lists/* RUN pip install --upgrade pip setuptools wheel # Create appuser early so all downloads happen as them RUN useradd -m -u 1000 appuser # Set cache dirs to appuser-owned locations from the start ENV HOME=/home/appuser ENV HF_HOME=/home/appuser/.cache/huggingface ENV TORCH_HOME=/home/appuser/.cache/torch WORKDIR /app RUN chown appuser:appuser /app # Install dependencies as root (fine for pip) COPY backend/requirements.txt ./backend/requirements.txt RUN pip install --no-cache-dir -r backend/requirements.txt # Pre-download models as appuser so file ownership is correct USER appuser RUN python -c "\ from transformers import MarianMTModel, MarianTokenizer; \ print('Downloading translation model...'); \ MarianTokenizer.from_pretrained('Helsinki-NLP/opus-mt-en-mul'); \ MarianMTModel.from_pretrained('Helsinki-NLP/opus-mt-en-mul'); \ print('Done.')" RUN python -c "\ from speechbrain.inference.TTS import Tacotron2; \ from speechbrain.inference.vocoders import HIFIGAN; \ print('Downloading TTS models...'); \ Tacotron2.from_hparams(source='Sunbird/sunbird-lug-tts', savedir='/home/appuser/tts_model'); \ HIFIGAN.from_hparams(source='speechbrain/tts-hifigan-ljspeech', savedir='/home/appuser/vocoder'); \ print('Done.')" RUN python -c "\ import whisper; \ print('Downloading Whisper...'); \ whisper.load_model('base'); \ print('Done.')" RUN python -c "import nltk; nltk.download('punkt'); nltk.download('punkt_tab')" # Copy app code USER root COPY backend/ ./backend/ COPY frontend/ ./frontend/ RUN chown -R appuser:appuser /app USER appuser WORKDIR /app/backend EXPOSE 7860 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]