Docker Production Deployment
Overview
For self-hosted production deployments, the TEA Platform provides a production Docker Compose configuration (docker-compose.yml) that differs from the development setup in several ways:
- Uses the pre-built image from GitHub Container Registry (ghcr.io) instead of building locally
- Production-optimised Next.js build
- Proper secret management via environment variables
- Database persistence with named volumes
- Health checks for both application and database
Azure Deployment
The official staging and production environments are hosted on Azure App Service and deployed automatically via GitHub Actions. This guide is for self-hosted deployments using Docker Compose.
Quick Start
1. Clone the Repository
git clone https://github.com/alan-turing-institute/AssurancePlatform.git
cd AssurancePlatform2. Create Production Environment File
cp .env.example .envEdit .env with production values:
# Application
NODE_ENV=production
NEXTAUTH_URL=https://your-domain.com
NEXTAUTH_SECRET=<generate-with-openssl-rand-base64-32>
# Database
DATABASE_URL=postgresql://tea:secure-password@db:5432/tea
POSTGRES_USER=tea
POSTGRES_PASSWORD=secure-password
POSTGRES_DB=tea
# GitHub OAuth (optional)
GITHUB_APP_CLIENT_ID=your-client-id
GITHUB_APP_CLIENT_SECRET=your-client-secret3. Deploy
docker-compose -f docker-compose.yml up -dThis pulls the latest image from ghcr.io/alan-turing-institute/assuranceplatform:latest and starts the application with PostgreSQL.
Production Configuration
Container Names
| Container | Service | Port |
|---|---|---|
tea_app | Next.js application | 3000 |
tea_postgres | PostgreSQL database | 5432 |
Reverse Proxy
For production, place the application behind a reverse proxy for SSL termination:
Using nginx:
server {
listen 443 ssl;
server_name tea.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Database Persistence
Database data is persisted via a named Docker volume (postgres_data). To use a bind mount instead:
volumes:
postgres_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/postgresHealth Checks
The application includes a health check endpoint:
/api/health— Returns 200 when the application is ready
Updating
To update to a new version:
# Pull latest image
docker-compose -f docker-compose.yml pull
# Restart with new image
docker-compose -f docker-compose.yml up -dOr to build from source:
git pull origin main
docker-compose -f docker-compose.yml up -d --buildTroubleshooting
View Logs
docker-compose -f docker-compose.yml logs -f tea_appDatabase Connection Issues
- Verify
DATABASE_URLis correct in your.envfile - Check database container is running:
docker ps | grep tea_postgres - Ensure network connectivity between containers
Application Not Starting
- Check logs for error messages
- Verify all required environment variables are set (
NEXTAUTH_SECRET,DATABASE_URL) - Ensure database migrations have run:
docker exec tea_app npx prisma migrate deploy
Further Reading
- Deployment Overview — General deployment guidance
- Database Management — Backup and restore procedures