How to Set Up a Docker Compose Environment with Local LLM Server for Speech-to-Speech
Use the pre-configured docker-compose.yml in the huggingface/speech-to-speech repository to launch a local LLM backend alongside the speech-to-speech pipeline with GPU support out of the box.
The speech-to-speech repository by Hugging Face provides a production-ready Docker Compose configuration that eliminates manual setup. According to the source code in docker-compose.yml, the stack deploys two interconnected services: a GPU-accelerated llama.cpp server for local LLM inference and the speech-to-speech pipeline that routes all generation requests to this backend.
Architecture Overview
The Docker Compose environment orchestrates two specialized containers:
| Service | Purpose | Key Implementation Details |
|---|---|---|
llama |
Local LLM server | Runs ghcr.io/ggml-org/llama.cpp:server-cuda with OpenAI-compatible API on port 8080 |
pipeline |
Speech-to-speech application | Custom build from repository Dockerfile, exposes public API on port 8765 |
Both services mount a shared ./cache/ volume at /root/.cache/ for model persistence and request NVIDIA GPU access through identical deploy.resources.reservations.devices configurations.
Prerequisites
Before deploying, verify your environment meets these requirements:
- Docker Engine 20.10+ with NVIDIA Container Toolkit installed
- Compatible NVIDIA driver for the CUDA runtime in the
llama.cppimage - At least 4 GB free disk space for the default GGUF model download
- Git for cloning the repository
Step-by-Step Setup
Follow these commands to launch your local speech-to-speech environment with integrated LLM backend:
# 1. Clone the repository
git clone https://github.com/huggingface/speech-to-speech.git
cd speech-to-speech
# 2. (Optional) Customize configuration
# Edit docker-compose.yml to change model_id or GPU device_ids
# 3. Pull the GPU-enabled LLM image
docker pull ghcr.io/ggml-org/llama.cpp:server-cuda
# 4. Build and start all services
docker compose up --build -d
# 5. Verify LLM server health
curl http://localhost:8080/v1/models
# 6. Test the complete speech-to-speech pipeline
curl -X POST http://localhost:8765/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"ggml-org/gemma-4-E4B-it-GGUF","messages":[{"role":"user","content":"Hello!"}]}'
Service Configuration Details
LLM Service (llama)
As defined in docker-compose.yml lines 5-31, the LLM container uses this configuration:
services:
llama:
image: ghcr.io/ggml-org/llama.cpp:server-cuda
command:
- -hf
- ggml-org/gemma-4-E4B-it-GGUF
- -np
- "2"
- -c
- "65536"
- -fa
- "on"
- --swa-full
- --host
- 0.0.0.0
- --port
- "8080"
ports:
- 8080:8080/tcp
volumes:
- ./cache/:/root/.cache/
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ['0']
capabilities: [gpu]
Key parameters:
-hf ggml-org/gemma-4-E4B-it-GGUF— Downloads and serves the Gemma 4B instruction-tuned model-c 65536— Allocates 65,536 tokens of context window-np 2— Enables 2 parallel completion slotsdevice_ids: ['0']— Binds to first available GPU (modify for multi-GPU systems)
Pipeline Service
The speech-to-speech container, configured in docker-compose.yml lines 32-70, connects to the LLM backend internally:
pipeline:
build:
context: .
dockerfile: ${DOCKERFILE:-Dockerfile}
command:
- speech-to-speech
- serve
- --host
- 0.0.0.0
- --port
- "8765"
- --llm_backend
- responses-api
- --model_name
- ggml-org/gemma-4-E4B-it-GGUF
- --responses_api_base_url
- http://llama:8080/v1
ports:
- 8765:8765/tcp
volumes:
- ./cache/:/root/.cache/
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ['0']
capabilities: [gpu]
The --responses_api_base_url http://llama:8080/v1 argument routes all LLM calls to the internal Docker network address, keeping LLM traffic isolated from the host network while exposing only the speech-to-speech API endpoint.
How the Components Interact
Understanding the data flow helps with troubleshooting and customization:
-
Model caching — On first startup, the
llamaservice downloads the GGUF model to./cache/. Subsequent restarts reuse cached weights. -
Internal networking — The
pipelineservice resolveshttp://llama:8080/v1through Docker's embedded DNS, forwarding all generation requests to the local LLM. -
Command entry point — In
src/speech_to_speech/cli.py(lines 156-166), thespeech-to-speech servecommand implements the server logic invoked by the container'scommandarray. -
GPU scheduling — Both containers request the same GPU device, with
llama.cpphandling inference and the pipeline managing STT/TTS acceleration.
Customization Options
Switch to CPU-Only Deployment
For systems without NVIDIA GPUs, override the Dockerfile selection:
DOCKERFILE=Dockerfile.cpu docker compose up --build -d
Use a Different GGUF Model
Modify the -hf argument in docker-compose.yml:
command:
- -hf
- your-org/your-model-GGUF # Replace model identifier
Adjust GPU Device Assignment
Change device_ids in both services to target specific GPUs:
device_ids: ['1'] # Use second GPU
Verification and Health Checks
Confirm successful deployment with these diagnostic commands:
# Check LLM server model availability
curl -s http://localhost:8080/v1/models | jq '.data[].id'
# Verify speech-to-speech endpoint responsiveness
curl -s http://localhost:8765/v1/models
# Inspect container logs for errors
docker compose logs -f llama
docker compose logs -f pipeline
Troubleshooting Common Issues
| Symptom | Cause | Resolution |
|---|---|---|
nvidia-smi fails inside container |
NVIDIA runtime not configured | Install NVIDIA Container Toolkit and restart Docker |
| Port 8080 already bound | Conflicting service on host | Change ports: mapping to 8081:8080/tcp |
| Model download hangs | Network or permission issue | Verify ./cache/ is writable and check connectivity |
| GPU memory exhausted | Model too large for VRAM | Select smaller GGUF quantization or reduce -c context size |
| Pipeline cannot reach LLM | DNS resolution failure | Ensure both containers on same Docker network: docker network inspect speech-to-speech_default |
Summary
- The huggingface/speech-to-speech repository provides a complete
docker-compose.ymlfor local LLM deployment - Two services run:
llama(LLM inference) andpipeline(speech-to-speech API) - GPU acceleration requires NVIDIA Container Toolkit with matching driver versions
- Shared
./cache/volume persists downloaded models across restarts - The
pipelineservice routes LLM requests internally viahttp://llama:8080/v1 - Override
DOCKERFILEenvironment variable to select alternative container builds
Frequently Asked Questions
What LLM models are compatible with this setup?
Any GGUF-format model hosted on Hugging Face works with the llama.cpp backend. The default gemma-4-E4B-it-GGUF provides a balance of quality and speed, but you can substitute larger models like Llama 3 or Mistral by changing the -hf parameter. Ensure your GPU has sufficient VRAM for the selected model's activation weights.
Do I need an OpenAI API key for local inference?
No. The --llm_backend responses-api configuration redirects all generation to the local llama container. The API compatibility layer mimics OpenAI's chat completion format, allowing tools designed for OpenAI to work with your local model without code changes.
How do I monitor GPU utilization across both containers?
Run docker exec combined with nvidia-smi to check allocation per container, or use nvidia-smi dmon on the host for continuous monitoring. Since both services request the same GPU device, their processes appear together in host-level GPU statistics.
Can I scale the LLM service to multiple replicas?
Docker Compose's default networking complicates multi-replica LLM deployments because the pipeline service expects a single llama hostname. For horizontal scaling, migrate to Kubernetes or implement a load balancer container that the pipeline targets instead of connecting directly to llama.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →