178 lines
5.5 KiB
YAML
178 lines
5.5 KiB
YAML
services:
|
|
# The web process talks to this narrowly configured proxy over the Compose
|
|
# network; the host Docker socket is never mounted into the web container.
|
|
docker-socket-proxy:
|
|
image: tecnativa/docker-socket-proxy:0.3.0
|
|
container_name: tts-voice-creator-docker-proxy
|
|
restart: unless-stopped
|
|
# NOT read_only: the entrypoint sed's its own haproxy.cfg.template into
|
|
# haproxy.cfg at startup, in the same directory the template ships in --
|
|
# read_only crash-looped it ("Read-only file system"), and a tmpfs mount
|
|
# over that directory only trades one failure for another by hiding the
|
|
# template it needs to read (confirmed live: "No such file or
|
|
# directory"). The real hardening here is cap_drop: ALL,
|
|
# no-new-privileges, and the Docker socket itself being mounted :ro.
|
|
cap_drop:
|
|
- ALL
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
environment:
|
|
CONTAINERS: "1"
|
|
POST: "1"
|
|
IMAGES: "0"
|
|
NETWORKS: "0"
|
|
VOLUMES: "0"
|
|
SERVICES: "0"
|
|
TASKS: "0"
|
|
SWARM: "0"
|
|
SYSTEM: "0"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
networks:
|
|
- dgx_net
|
|
|
|
tts-voice-creator-clone-and-design-2:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
image: ghcr.io/martin-b78/tts-voice-creator-clone-and-design-2:${APP_TAG:-latest}
|
|
container_name: tts-voice-creator-clone-and-design-2
|
|
restart: unless-stopped
|
|
|
|
# The application writes only to the explicitly mounted data paths below.
|
|
# Keep the image filesystem immutable even if an endpoint is compromised.
|
|
read_only: true
|
|
cap_drop:
|
|
- ALL
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
tmpfs:
|
|
- /tmp:size=1g,mode=1777
|
|
|
|
# Keep a runaway OCR/import/generation request from consuming all host RAM.
|
|
# Override these per machine when large PDF jobs need more headroom:
|
|
# APP_MEM_LIMIT=12g APP_MEM_RESERVATION=2g docker compose up -d
|
|
mem_limit: "${APP_MEM_LIMIT:-8g}"
|
|
mem_reservation: "${APP_MEM_RESERVATION:-2g}"
|
|
|
|
ports:
|
|
- "7890:7890"
|
|
|
|
depends_on:
|
|
- docker-socket-proxy
|
|
|
|
volumes:
|
|
- ${VOICE_HOST_DIR:-/home/sparky/Media/_Sounds/TTS_Voices}:/voices:rw
|
|
- ./config:/home/app/.config/tts-voice-creator:rw # settings, presets, routes
|
|
- ./logs:/logs:rw # application logs
|
|
- /home/sparky/Docker/tts-dgx-spark-faster-qwen3-tts/config:/tts-config:rw
|
|
- ./static:/app/static:ro
|
|
- ./server.py:/app/server.py:ro
|
|
- ./core:/app/core:ro
|
|
- ./routes:/app/routes:ro
|
|
- ./workflows:/app/workflows:ro
|
|
- ./VERSION:/app/VERSION:ro
|
|
- ./CHANGELOG.md:/app/CHANGELOG.md:ro
|
|
|
|
environment:
|
|
- PYTHONUNBUFFERED=1
|
|
- VOICES_DIR=/voices
|
|
- OUTPUT_DIR=/voices/active_voices
|
|
# Containers that load WAV files and need a restart after voice changes
|
|
- TTS_CONTAINER_NAME=tts-faster-qwen3-tts-voiceclone
|
|
- TTS_CONTAINER_NAMES=tts-faster-qwen3-tts-voiceclone,tts-faster-qwen3-tts-streaming
|
|
- VOICE_DESIGN_MODEL=Qwen3-TTS-12Hz-1.7B-VoiceDesign
|
|
- DOCKER_HOST=tcp://docker-socket-proxy:2375
|
|
# Word-level forced aligner sidecar; empty disables word timing (sentence timing keeps working)
|
|
- ALIGNER_URL=${ALIGNER_URL-http://tts-aligner:8000}
|
|
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
|
|
networks:
|
|
- dgx_net
|
|
|
|
# Word-level forced aligner (torchaudio MMS_FA). Separate image so the app stays torch-free. Reachable only on
|
|
# the Compose network (no published port); the app calls http://tts-aligner:8000. Weights (~1.2 GB) are
|
|
# downloaded once into the named volume; after that the service needs no outbound access.
|
|
tts-aligner:
|
|
build:
|
|
context: ./aligner
|
|
image: tts-aligner:local
|
|
container_name: tts-aligner
|
|
restart: unless-stopped
|
|
read_only: true
|
|
cap_drop:
|
|
- ALL
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
tmpfs:
|
|
- /tmp:size=256m,mode=1777
|
|
mem_limit: "${ALIGNER_MEM_LIMIT:-3g}"
|
|
cpus: "${ALIGNER_CPUS:-4}"
|
|
environment:
|
|
- ALIGNER_DEVICE=cpu
|
|
- ALIGNER_THREADS=4
|
|
expose:
|
|
- "8000"
|
|
volumes:
|
|
- aligner-models:/models:rw
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8000/health"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 60s
|
|
networks:
|
|
- dgx_net
|
|
|
|
# Optional GPU variant: `docker compose --profile gpu up -d --build tts-aligner-gpu` (stop tts-aligner first;
|
|
# both answer to the name tts-aligner). Off by default because the DGX GPU is often full.
|
|
tts-aligner-gpu:
|
|
profiles: ["gpu"]
|
|
build:
|
|
context: ./aligner
|
|
args:
|
|
TORCH_INDEX: https://download.pytorch.org/whl/cu130
|
|
image: tts-aligner:gpu
|
|
container_name: tts-aligner-gpu
|
|
restart: unless-stopped
|
|
read_only: true
|
|
cap_drop:
|
|
- ALL
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
tmpfs:
|
|
- /tmp:size=256m,mode=1777
|
|
mem_limit: "${ALIGNER_MEM_LIMIT:-3g}"
|
|
environment:
|
|
- ALIGNER_DEVICE=cuda
|
|
expose:
|
|
- "8000"
|
|
volumes:
|
|
- aligner-models:/models:rw
|
|
deploy:
|
|
resources:
|
|
reservations:
|
|
devices:
|
|
- driver: nvidia
|
|
count: 1
|
|
capabilities: [gpu]
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8000/health"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 60s
|
|
networks:
|
|
dgx_net:
|
|
aliases:
|
|
- tts-aligner
|
|
|
|
networks:
|
|
dgx_net:
|
|
external: true
|
|
|
|
volumes:
|
|
aligner-models:
|