- nginx: return 200 OK on GET / for load balancer health checks - Dockerfile: set HF_HOME=/app/models so Hub downloads persist in mounted volume - Dockerfile: add /app/data directory and volume declaration - docker-compose: explicit volume mounts for models, data, lora, output - README: document where to put training files and find output - .gitignore: exclude volume mount directories (models/, data/, lora/, output/)
Docker Support for VoxCPM Training WebUI
Run the VoxCPM LoRA fine-tuning WebUI in a Docker container with full GPU support and nginx reverse proxy.
Prerequisites
- Docker Engine 19.03+ with NVIDIA Container Toolkit
- NVIDIA GPU with CUDA 12.4+ compatible drivers
- At least 16 GB GPU VRAM (24 GB+ recommended for larger models)
Quick Start
# From the project root directory:
docker compose -f docker/docker-compose.yml up --build
This starts:
- training-webui — the Gradio-based training interface on port 7860
- nginx — reverse proxy serving the WebUI at
http://localhost/webui/
Access the WebUI at http://localhost/webui/.
Volume Mounts
The compose file maps host directories to container paths. Create these directories at the project root before starting:
VoxCPM/
├── docker/
│ ├── docker-compose.yml
│ ├── Dockerfile
│ └── nginx.conf
├── models/ ← Pretrained model weights (or auto-downloaded via HF)
│ ├── openbmb__VoxCPM2/
│ └── openbmb__VoxCPM1.5/
├── data/ ← Training manifests + audio files
│ ├── train.jsonl
│ ├── val.jsonl (optional)
│ └── audio/
│ ├── speaker1_001.wav
│ └── ...
├── lora/ ← LoRA training output (created automatically)
│ └── my-voice-2024/
│ ├── checkpoints/
│ ├── logs/
│ └── train_config.yaml
└── output/ ← Additional training artifacts
Mount Reference
| Host Path | Container Path | Purpose |
|---|---|---|
./models/ |
/app/models |
Pretrained model weights and HF cache (HF_HOME). Pre-populate with model dirs (e.g., openbmb__VoxCPM2/) or leave empty — models auto-download on first run and persist here. |
./data/ |
/app/data |
Training data. Put JSONL manifests and audio files here. In the WebUI, reference paths as /app/data/train.jsonl. |
./lora/ |
/app/lora |
LoRA checkpoint output. After training, find results in lora/<run-name>/checkpoints/. Also used to resume training from existing checkpoints. |
./output/ |
/app/output |
Miscellaneous training artifacts. |
Training Data Format
The train manifest is a JSONL file where each line references an audio file:
{"audio_path": "/app/data/audio/speaker1_001.wav", "text": "Hello world", "speaker": "speaker1"}
Use absolute container paths (/app/data/...) in your manifest so the container can find the files.
Models
If models/openbmb__VoxCPM2/ exists on the host, the app loads directly from that path — no network access needed. If the directory is empty or missing, from_pretrained falls back to snapshot_download from HuggingFace Hub.
The Dockerfile sets HF_HOME=/app/models so any Hub downloads land in the same mounted volume (matching the pattern in deploy/Dockerfile.voxcpm-unified). This means models persist across container restarts regardless of whether they were pre-populated or auto-downloaded.
Recommended: Pre-populate to avoid first-run download delay:
huggingface-cli download openbmb/VoxCPM2 --local-dir ./models/openbmb__VoxCPM2
The Dockerfile creates empty /app/models, /app/lora, /app/output directories, but the volume mounts override them with your host directories.
Health Check
The nginx proxy responds with 200 OK on GET / for load balancer health checks (AWS ALB, etc.). This is separate from the WebUI at /webui/.
curl http://localhost/
# OK
Direct Access (no proxy)
If you want to bypass nginx and access Gradio directly:
docker compose -f docker/docker-compose.yml up --build training-webui
Set GRADIO_ROOT_PATH= (empty) in the compose file when running without the proxy, then access at http://localhost:7860.
Building Manually
# Build the image
docker build -f docker/Dockerfile -t voxcpm-training .
# Run with GPU access (no reverse proxy)
docker run --gpus all -p 7860:7860 \
-v ./models:/app/models \
-v ./data:/app/data \
-v ./lora:/app/lora \
-v ./output:/app/output \
voxcpm-training
Environment Variables
| Variable | Default | Description |
|---|---|---|
GRADIO_SERVER_PORT |
7860 |
Port for the WebUI server |
GRADIO_ROOT_PATH |
"" |
URL prefix when behind a reverse proxy (e.g., /webui) |
Reverse Proxy
The included docker-compose.yml ships with an nginx reverse proxy that serves the WebUI at /webui/. The GRADIO_ROOT_PATH=/webui env var ensures Gradio generates correct URLs for assets and WebSocket connections.
Custom nginx config
Edit docker/nginx.conf to change the location prefix or add TLS.
Traefik Example (labels)
labels:
- "traefik.http.routers.voxcpm.rule=PathPrefix(`/webui`)"
- "traefik.http.services.voxcpm.loadbalancer.server.port=7860"
Viewing Training Logs
Training subprocess output is streamed to stdout, visible via:
docker compose -f docker/docker-compose.yml logs -f training-webui
Troubleshooting
- "no NVIDIA GPU detected": Ensure the NVIDIA Container Toolkit is installed and
docker run --gpus all nvidia-smiworks. - OOM errors: Reduce batch size in the WebUI or use a GPU with more VRAM.
- WebUI not accessible: Check that port 80 (nginx) or 7860 (direct) isn't blocked by a firewall.
- WebSocket errors behind proxy: Ensure your proxy forwards
UpgradeandConnectionheaders (the included nginx.conf handles this). - Health check failing: Ensure nginx is running —
curl http://localhost/should returnOK.