# syntax=docker/dockerfile:1.6 # # IndexTTS-2 served behind our own thin FastAPI wrapper (~150 lines in # app.py). Upstream ships only a Gradio webui; the existing csllpr # FastAPI fork is for v1 and dormant. We own the wrapper end-to-end. ARG CUDA_BASE=nvidia/cuda:12.8.0-cudnn-runtime-ubuntu22.04 FROM ${CUDA_BASE} ENV DEBIAN_FRONTEND=noninteractive \ PIP_ROOT_USER_ACTION=ignore \ PYTHONUNBUFFERED=1 \ PATH="/opt/venv/bin:${PATH}" RUN apt-get update \ && apt-get install -y --no-install-recommends \ python3.10 python3.10-venv python3-pip \ git ffmpeg libsndfile1 \ ca-certificates wget \ && rm -rf /var/lib/apt/lists/* \ && python3.10 -m venv /opt/venv # Pinned IndexTTS-2 SHA — bump in stack .env (INDEX_TTS_SHA build arg) # when you want upstream updates. # # Note on LFS: examples/emo_*.wav and examples/voice_*.wav in the # upstream repo are Git LFS objects, but the index-tts org has # repeatedly exhausted GitHub's LFS bandwidth budget — `git lfs pull` # in the build aborts with "This repository exceeded its LFS budget". # We don't need the examples for the wrapper to work; they're just # convenient starter audio. To stage real LFS-backed examples on the # host, fetch them once via the media CDN (a different code path that # doesn't count against the LFS API budget): # # curl -fsSL -o /worktank/index-tts/emotions/hate.wav \ # https://media.githubusercontent.com/media/index-tts/index-tts/main/examples/emo_hate.wav ARG INDEX_TTS_SHA=830f6f8f94a51fea23ab1d639027a86200075a4e RUN git clone https://github.com/index-tts/index-tts.git /opt/index-tts \ && cd /opt/index-tts && git checkout ${INDEX_TTS_SHA} # CUDA 12.8 torch wheels (per IndexTTS pyproject.toml's tool.uv.index # pin — same versions, same source). RUN pip install --no-cache-dir \ torch==2.8.0 torchaudio==2.8.0 \ --index-url https://download.pytorch.org/whl/cu128 # IndexTTS package + its long pinned-deps tail (numpy 1.26.2, transformers # 4.52.1, sentencepiece, librosa, descript-audiotools, jieba/g2p-en/cn2an, # WeTextProcessing, modelscope, accelerate, safetensors, etc.). # BigVGAN is vendored under indextts/ so it resolves without a pip dep. RUN cd /opt/index-tts && pip install --no-cache-dir -e . # Wrapper deps (FastAPI stack + soundfile for in-memory WAV encoding). RUN pip install --no-cache-dir \ fastapi 'uvicorn[standard]' python-multipart soundfile WORKDIR /app COPY app.py /app/app.py COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh EXPOSE 8000 # wget is in the base image (added above); curl is not. HEALTHCHECK --interval=30s --timeout=10s --start-period=600s --retries=3 \ CMD wget -q -O /dev/null http://127.0.0.1:8000/healthz || exit 1 ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]