- Dockerfile: Multi-stage build optimized for NestJS + Mediasoup
- docker-compose.yml: Full stack with SFU, PostgreSQL, and Hasura
Create a .env file in the project root:
# Server Configuration
PORT=3000
HOST=0.0.0.0
# Public URL (for frontend to connect)
PUBLIC_URL=http://localhost:3000
# WebRTC Configuration
RTC_MIN_PORT=40000
RTC_MAX_PORT=40100
# Announced IP for WebRTC
ANNOUNCED_IP=127.0.0.1
# Environment
NODE_ENV=production# Build and start all services
docker-compose up -d --build
# View logs
docker-compose logs -f sfu
# Stop all services
docker-compose down- SFU Application: http://localhost:3000
- Hasura Console: http://localhost:8080
- PostgreSQL: localhost:5432
3000- HTTP/WebSocket server40000-40100/udp- WebRTC media (UDP)40000-40100/tcp- WebRTC media (TCP)
Note: Docker limits the RTC port range to 101 ports (40000-40100) instead of the full 10,000 range. This is sufficient for most use cases (each connection uses ~2 ports).
You can override these in the .env file or directly in docker-compose.yml:
PUBLIC_URL- The URL clients use to connectANNOUNCED_IP- The IP address for WebRTC (use your server's public IP in production)RTC_MIN_PORT/RTC_MAX_PORT- Port range for WebRTC
-
Set your public IP in
.env:ANNOUNCED_IP=YOUR_PUBLIC_IP PUBLIC_URL=https://your-domain.com
-
Expose ports in firewall:
sudo ufw allow 3000/tcp sudo ufw allow 40000:40100/udp sudo ufw allow 40000:40100/tcp
-
Run behind Nginx (recommended):
server { listen 80; server_name your-domain.com; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }
-
Start ngrok:
ngrok http 3000
-
Update
.envwith ngrok URL:PUBLIC_URL=https://your-url.ngrok-free.app ANNOUNCED_IP=YOUR_PUBLIC_IP
-
Restart container:
docker-compose restart sfu
docker-compose logs -f sfudocker-compose exec sfu shdocker-compose ps
docker port sample-sfudocker-compose down -v
docker-compose build --no-cache
docker-compose up -d- CPU: 2 cores
- RAM: 2GB
- Disk: 10GB
- CPU: 4 cores
- RAM: 4GB
- Disk: 20GB
For development with hot-reload, use the local npm commands instead:
npm run start:devThe Docker setup is optimized for production deployments.
- Change Hasura Admin Secret in production
- Use HTTPS (not HTTP) with SSL certificates
- Limit RTC ports based on expected concurrent users
- Set strong PostgreSQL password
- Use environment variables for secrets (never commit
.env)
- Check if container is running:
docker-compose ps - Check logs:
docker-compose logs sfu - Verify PUBLIC_URL matches your access URL
- Verify ANNOUNCED_IP is set to your public IP
- Check firewall allows RTC ports (40000-40100)
- Ensure browser has mic/camera permissions
- Clear Docker cache:
docker system prune -a - Rebuild:
docker-compose build --no-cache
Increase RTC port range in docker-compose.yml:
ports:
- "40000-40200:40000-40200/udp" # 201 ports
- "40000-40200:40000-40200/tcp"And update .env:
RTC_MAX_PORT=40200Rule of thumb: Each user needs ~2 ports (one for send, one for receive).