Market Data Service is a high-performance financial data API that provides comprehensive Symbol prices of different markets through both RESTful endpoints and real-time WebSocket connections.
Note: This guide covers production deployment with fully containerized SSL certificate management. For local development, see LOCAL_DEV_SETUP.md. For Docker usage details, see DOCKER.md.
Complete guide for deploying Market Data Service to production with fully containerized SSL certificate management.
This deployment is fully containerized, including:
# Clone repository
git clone <your-repo-url>
cd market-data-service
# Create .env file for production
cat > .env << EOF
# Database Configuration
DB_USER=postgres
DB_PASSWORD=your_secure_password_here
DB_NAME=financial_data
# Application Configuration
NODE_ENV=production
PORT=3000
CORS_ORIGIN=https://yourdomain.com
JWT_SECRET=your_secure_jwt_secret_here
LOG_LEVEL=info
# SSL Configuration
DOMAIN_NAME=yourdomain.com
SSL_EMAIL=your-email@example.com
EOF
Important: Replace all placeholder values with your actual values.
# Start all services except certbot (we'll get certificates first)
docker-compose -f docker-compose.prod.yml up -d db api nginx
# Verify services are running
docker-compose -f docker-compose.prod.yml ps
# Check logs
docker-compose -f docker-compose.prod.yml logs -f
Option A: Production Certificate (Recommended)
# Obtain production SSL certificate
DOMAIN_NAME=yourdomain.com \
SSL_EMAIL=your-email@example.com \
docker-compose -f docker-compose.prod.yml run --rm certbot-init
Option B: Staging Certificate (For Testing)
# Test with Let's Encrypt staging server (doesn't count against rate limits)
DOMAIN_NAME=yourdomain.com \
SSL_EMAIL=your-email@example.com \
SSL_STAGING=1 \
docker-compose -f docker-compose.prod.yml run --rm certbot-init
What this does:
certbot_etc# Restart nginx to load SSL certificates
docker-compose -f docker-compose.prod.yml restart nginx
# Start certbot for automatic renewal
docker-compose -f docker-compose.prod.yml up -d certbot
# Check all services are running
docker-compose -f docker-compose.prod.yml ps
# Test HTTP (should redirect to HTTPS)
curl -I http://yourdomain.com
# Test HTTPS
curl https://yourdomain.com/health
# Test API endpoint
curl https://yourdomain.com/api/health
Certificates are automatically renewed every 12 hours by the certbot container. The renewal process:
No manual intervention required!
# Force certificate renewal
docker-compose -f docker-compose.prod.yml exec certbot certbot renew --force-renewal
# Restart nginx to load new certificates
docker-compose -f docker-compose.prod.yml restart nginx
# View certificate information
docker-compose -f docker-compose.prod.yml exec certbot certbot certificates
# Check certificate expiry
docker-compose -f docker-compose.prod.yml exec certbot openssl x509 -in /etc/letsencrypt/live/yourdomain.com/cert.pem -noout -dates
# All services
docker-compose -f docker-compose.prod.yml logs -f
# Specific service
docker-compose -f docker-compose.prod.yml logs -f api
docker-compose -f docker-compose.prod.yml logs -f nginx
docker-compose -f docker-compose.prod.yml logs -f certbot
docker-compose -f docker-compose.prod.yml logs -f db
# API health
curl https://yourdomain.com/health
# Container health status
docker-compose -f docker-compose.prod.yml ps
Key environment variables in .env:
| Variable | Description | Required |
|---|---|---|
DB_PASSWORD |
PostgreSQL password | Yes |
JWT_SECRET |
JWT secret key | Yes |
DOMAIN_NAME |
Your domain name | Yes |
SSL_EMAIL |
Email for Let's Encrypt | Yes |
CORS_ORIGIN |
Allowed CORS origins | Recommended |
Nginx configuration is in nginx/nginx.prod.conf. The domain name is automatically substituted at runtime from the DOMAIN_NAME environment variable.
Certificates are stored in Docker volumes:
certbot_etc → /etc/letsencrypt in containers/etc/letsencrypt/live/DOMAIN_NAME/fullchain.pem/etc/letsencrypt/live/DOMAIN_NAME/privkey.pemProblem: certbot-init fails with "Connection refused" or "Challenge failed"
Solutions:
Verify domain DNS points to your server:
dig yourdomain.com
nslookup yourdomain.com
Verify ports 80 and 443 are open:
sudo ufw status
# If needed: sudo ufw allow 80 && sudo ufw allow 443
Check nginx is running and accessible:
curl http://yourdomain.com/.well-known/acme-challenge/test
Use staging server first to test:
SSL_STAGING=1 docker-compose -f docker-compose.prod.yml run --rm certbot-init
Problem: Nginx fails to start with "SSL certificate not found"
Solutions:
Verify certificates exist:
docker-compose -f docker-compose.prod.yml exec nginx ls -la /etc/letsencrypt/live/
Check DOMAIN_NAME matches certificate domain:
# In .env file
DOMAIN_NAME=yourdomain.com # Must match exactly
Restart nginx:
docker-compose -f docker-compose.prod.yml restart nginx
Problem: Certificates expire without renewal
Solutions:
Check certbot container is running:
docker-compose -f docker-compose.prod.yml ps certbot
Check certbot logs:
docker-compose -f docker-compose.prod.yml logs certbot
Manually test renewal:
docker-compose -f docker-compose.prod.yml exec certbot certbot renew --dry-run
Problem: New certificates not picked up by nginx
Solutions:
Check reload signal file:
docker-compose -f docker-compose.prod.yml exec nginx ls -la /var/run/certbot-reload/
Manually reload nginx:
docker-compose -f docker-compose.prod.yml exec nginx nginx -s reload
Restart nginx:
docker-compose -f docker-compose.prod.yml restart nginx
DB_PASSWORD and JWT_SECRETbash
docker-compose -f docker-compose.prod.yml pull
docker-compose -f docker-compose.prod.yml up -d
Backup: Regularly backup database and SSL certificates: ```bash
docker-compose -f docker-compose.prod.yml exec db pg_dump -U postgres financial_data > backup.sql
# Backup certificates (optional, they auto-renew) docker run --rm -v market-data-service_certbot_etc:/data -v $(pwd):/backup alpine tar czf /backup/certs_backup.tar.gz -C /data .
5. **Monitor Logs**: Set up log monitoring and alerting
6. **Rate Limiting**: Adjust rate limits in `nginx/nginx.prod.conf` as needed
## 📝 Maintenance
### Update Application
```bash
# Pull latest code
git pull
# Rebuild and restart
docker-compose -f docker-compose.prod.yml up -d --build
# Verify
docker-compose -f docker-compose.prod.yml ps
curl https://yourdomain.com/health
# Create backup
docker-compose -f docker-compose.prod.yml exec db pg_dump -U postgres financial_data > backup_$(date +%Y%m%d).sql
# Restore from backup
docker-compose -f docker-compose.prod.yml exec -T db psql -U postgres financial_data < backup_20250101.sql
docker-compose -f docker-compose.prod.yml exec certbot certbot certificates
docker-compose ps)curl -v)If you encounter issues:
docker-compose -f docker-compose.prod.yml logsdocker-compose -f docker-compose.prod.yml configdocker-compose -f docker-compose.prod.yml ps