# Piper neural-TTS HTTP server — the read-aloud backend Petal proxies to. # # One image, any voice: the model is named by PIPER_VOICE at runtime and # downloaded into the shared /voices volume on first start. Each Piper server # loads exactly one voice, so a new language is a new service in # docker-compose.yml, not a new image (English and Chinese today; pt-PT lands # with the Portuguese pair). # # python:3.12 rather than 3.13 — piper-tts pulls onnxruntime, whose wheel # coverage for 3.13 still lags. FROM python:3.12-slim RUN pip install --no-cache-dir "piper-tts[http]" \ && useradd -m -u 10002 piper ENV PIPER_VOICE=en_US-amy-medium \ PIPER_DATA_DIR=/voices \ PIPER_PORT=5000 RUN mkdir -p /voices && chown piper:piper /voices VOLUME ["/voices"] COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh USER piper EXPOSE 5000 # The server has no dedicated health route, so synthesizing a single word is # the honest check: it proves the model loaded, not just that a port is open. HEALTHCHECK --interval=60s --timeout=20s --start-period=180s --retries=3 \ CMD python -c "import os,urllib.request,json; \ urllib.request.urlopen(urllib.request.Request('http://127.0.0.1:'+os.environ['PIPER_PORT']+'/', \ data=json.dumps({'text':'ok','voice':os.environ['PIPER_VOICE']}).encode(), \ headers={'Content-Type':'application/json'}), timeout=15).read(1)" ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]