The Exchange platform uses automated CI/CD with GitHub Actions to build, push, and deploy Docker images to production. This guide covers the production deployment strategy and best practices.
Deployment architecture
The production deployment follows a GitOps workflow:
- Code push to
main branch triggers the CI/CD pipeline
- Docker images are built for all services
- Images are pushed to Docker Hub with commit SHA tags
- Deployment manifests are updated in a separate ops repository
- Kubernetes/Docker pulls and deploys the new images
GitHub Actions workflow
The production deployment is automated using GitHub Actions:
Trigger on push to main
The workflow runs on every push to the main branch:.github/workflows/production.yml
name: Continuous Deployment (Production)
on:
push:
branches: ["main"]
Docker login
Authenticate to Docker Hub using repository secrets:- name: Docker login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
Build and push images
Each service is built and pushed with the commit SHA as the tag:- name: Build and push exchange-router images
uses: docker/build-push-action@v4
with:
context: .
file: docker/Dockerfile.router
push: true
tags: jogeshwar01/exchange-router:${{ github.sha }}
This is repeated for all four services:
exchange-router
exchange-ws-stream
exchange-db-processor
exchange-engine
Update deployment manifests
The workflow automatically updates the ops repository:- name: Clone exchange-ops repo, update image tags, and push tags
env:
PAT: ${{ secrets.PAT }}
run: |
git clone https://github.com/jogeshwar01/exchange-ops.git
cd exchange-ops
sed -i 's|image: jogeshwar01/exchange-router:.*|image: jogeshwar01/exchange-router:${{ github.sha }}|' backend/deployment.yml
sed -i 's|image: jogeshwar01/exchange-ws-stream:.*|image: jogeshwar01/exchange-ws-stream:${{ github.sha }}|' websocket/deployment.yml
sed -i 's|image: jogeshwar01/exchange-db-processor:.*|image: jogeshwar01/exchange-db-processor:${{ github.sha }}|' db-processor/deployment.yml
sed -i 's|image: jogeshwar01/exchange-engine:.*|image: jogeshwar01/exchange-engine:${{ github.sha }}|' engine/deployment.yml
git config user.name "GitHub Actions Bot"
git config user.email "[email protected]"
git add .
git commit -m "deploy: update exchange image tags to ${{ github.sha }}"
git push https://${PAT}@github.com/jogeshwar01/exchange-ops.git main
Required GitHub secrets
Configure the following secrets in your GitHub repository settings:
DOCKER_USERNAME
Your Docker Hub username for pushing images. DOCKER_PASSWORD
Your Docker Hub password or access token.Use a Docker Hub access token instead of your password for better security.
PAT (Personal Access Token)
GitHub Personal Access Token with repo scope to update the ops repository.Generate at: https://github.com/settings/tokensRequired scopes:
repo - Full control of private repositories
Setting up GitHub secrets
- Go to your repository on GitHub
- Navigate to Settings → Secrets and variables → Actions
- Click New repository secret
- Add each secret with its corresponding value
Production server setup
Connect to your server
SSH into your production server:ssh -i key.pem ubuntu@<server-ip>
Install Docker
Install Docker and Docker Compose:# Add Docker's official GPG key
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Configure Docker permissions
Add your user to the docker group:sudo usermod -aG docker $USER
newgrp docker
docker ps # Verify it works
Clone the ops repository
git clone https://github.com/jogeshwar01/exchange-ops.git
cd exchange-ops
Configure environment
Create and configure the .env file:cp .env.example .env
nano .env # Edit with production values
Use strong passwords and secure credentials in production!
Production environment variables
Critical production configurations:
Database configuration
POSTGRES_HOST=exchange-postgres
POSTGRES_DB=exchange-db
POSTGRES_USER=<strong-username>
POSTGRES_PASSWORD=<strong-password>
POSTGRES_PORT=5432
PG__POOL_MAX_SIZE=16
Redis configuration
REDIS_URL=redis://exchange-redis:6379
Service endpoints
SERVER_ADDR=0.0.0.0:8080
WS_STREAM_URL=0.0.0.0:4000
PostgreSQL optimization
Increase max connections for high load:
db:
command: -c 'max_connections=800'
shm_size: 1gb
Memory limits
Adjust based on your server capacity:
deploy:
resources:
limits:
memory: 5G
Connection pooling
Configure optimal pool size:
PG__POOL_MAX_SIZE=16 # Adjust based on load
Redis persistence
Configure Redis snapshot frequency:
redis:
command: redis-server --save 20 1 --loglevel warning
This saves to disk if at least 1 key changed in 20 seconds.
Monitoring and health checks
Check service status
# View running containers
docker ps
# Check specific service logs
docker logs -f exchange-router
Resource monitoring
# Container resource usage
docker stats
# System resources
top
htop
Database health
# Check PostgreSQL
docker exec -it exchange-postgres psql -U root -d exchange-db -c "SELECT COUNT(*) FROM trades;"
# Check Redis
docker exec -it exchange-redis redis-cli ping
Rollback strategy
If a deployment fails, rollback to a previous version:
Identify the previous commit SHA
Update deployment manifests
cd exchange-ops
sed -i 's|image: jogeshwar01/exchange-router:.*|image: jogeshwar01/exchange-router:<previous-sha>|' backend/deployment.yml
# Repeat for other services
Commit and push
git add .
git commit -m "rollback: revert to <previous-sha>"
git push
Pull and restart services
docker compose pull
docker compose up -d
Security best practices
Always follow these security practices in production:
- Use strong passwords for database and Redis
- Store secrets in GitHub Secrets, never in code
- Use TLS/SSL for all external connections
- Enable firewall rules to restrict access
- Regularly update dependencies and Docker images
- Implement rate limiting on API endpoints
- Enable audit logging for all transactions
- Use read replicas for database scalability
Backup strategy
Database backups
# Automated daily backup
docker exec exchange-postgres pg_dump -U root exchange-db > backup-$(date +%Y%m%d).sql
Redis backups
Redis automatically saves to:
docker/redis-data/dump.rdb
Copy this file regularly to backup storage.
Scaling considerations
Horizontal scaling
For high-traffic deployments:
- Run multiple instances of
router behind a load balancer
- Use a dedicated Redis cluster
- Implement database read replicas
- Use separate servers for each service
Vertical scaling
Increase resources per service:
deploy:
resources:
limits:
memory: 10G
cpus: '4'
Next steps