This repository provides comprehensive Docker-based infrastructure setups for a PostgreSQL High Availability (HA) cluster and a Temporal workflow orchestration engine. These components are designed to work seamlessly together, enabling scalable, fault-tolerant data persistence and workflow management for development and production environments.
The infrastructure consists of two main components that can be deployed independently or together:
-
PostgreSQL HA Cluster: A production-ready, three-node PostgreSQL cluster with automatic failover, load balancing, and monitoring capabilities.
-
Temporal Workflow Engine: A distributed workflow orchestration platform that can utilize the HA PostgreSQL cluster for persistent storage.
┌─────────────────┐ ┌─────────────────┐
│ Applications │────│ Temporal UI │
│ │ │ (Port 8080) │
└─────────────────┘ └─────────────────┘
│ │
└───────────────────────┼──────────────────────┐
│ │
┌─────────────┴────────────┐ ┌─────┴─────┐
│ Temporal Server │ │ HAProxy │
│ (Port 7233) │ │ (Ports: │
└──────────────────────────┘ │ 6543,7000 │
│ │ 8404) │
└─────────────────────┼───────────┘
│
┌──────────────────────────────┼─────────────┐
│ │ │
┌───────▼──────┐ ┌───────▼──────┐ │
│ PostgreSQL │ │ PostgreSQL │ │
│ Node 1 │ │ Node 2 │ │
│ (Primary) │ │ (Replica) │ │
└──────────────┘ └──────────────┘ │
│ │ │
┌───────▼──────┐ ┌───────▼──────┐ │
│ PostgreSQL │ │ PostgreSQL │ │
│ Node 3 │ │ Node 3 │ │
│ (Replica) │ │ (Replica) │ │
└──────────────┘ └──────────────┘ │
│ │ │
└──────────────────────────────┼─────────────┘
│
┌─────▼─────┐
│ etcd │
│ (Port 2379│
└───────────┘
A robust, production-ready PostgreSQL High Availability cluster built with industry-standard tools:
- PostgreSQL 15: Enterprise-grade relational database with streaming replication
- Patroni: Cluster management framework handling leader election, failover, and configuration
- etcd: Distributed key-value store providing coordination and consensus for Patroni
- HAProxy: Advanced load balancer with health checks and traffic routing
- Automatic Failover: Seamless leader election and failover within seconds
- Read Load Balancing: Distribute read queries across replica nodes
- Health Monitoring: Comprehensive health checks for all cluster components
- Persistent Storage: Docker volumes ensure data persistence across container restarts
- Streaming Replication: Synchronous and asynchronous replication options
- 6543: Primary (read-write) endpoint via HAProxy
- 7000: Replica (read-only) endpoint via HAProxy
- 8404: HAProxy statistics dashboard
- 5433-5435: Direct access to individual PostgreSQL nodes (postgres1, postgres2, postgres3)
- 8008-8010: Patroni REST API endpoints for each node
- 2379/2380: etcd client/peer communication
Located in postgres-ha/scripts/:
init-cluster.sh: Initializes the cluster bootstrap processhealth-check.sh: Performs comprehensive health checks on all componentsmanage-cluster.sh: Cluster lifecycle management (start/stop/restart/status/logs/failover testing)clean-volumes.sh: Resets data volumes for fresh cluster initialization
A complete Temporal workflow orchestration platform deployment:
- Temporal Server: Core workflow engine handling workflow execution, task queues, and state management
- Temporal UI: Web-based interface for workflow monitoring, debugging, and management
- Temporal Admin Tools: Command-line utilities for cluster administration and troubleshooting
- Auto-Setup Images: Pre-configured containers with automatic database schema setup
- Dynamic Configuration: Runtime configuration overrides via YAML files
- CORS Support: Configurable cross-origin resource sharing for web applications
- Multi-Database Support: Compatible with PostgreSQL, MySQL, Cassandra, and Elasticsearch
- 7233: Temporal server gRPC API
- 8080: Temporal UI web interface
- External PostgreSQL: Connects to existing PostgreSQL instances (recommended for HA setups)
- Embedded PostgreSQL: Includes its own PostgreSQL container for development
- Docker: Version 20.10 or later
- Docker Compose: Version 2.0 or later
- Bash: For running management scripts
- Network Connectivity: Ensure required ports are available and accessible
- System Resources: Minimum 4GB RAM, 2 CPU cores recommended for full deployment
-
Clone the repository:
git clone <repository-url> cd infra
-
Deploy PostgreSQL HA Cluster:
cd postgres-ha cp .env.example .env # Edit .env with your desired passwords docker-compose up -d ./scripts/health-check.sh
-
Deploy Temporal:
cd ../temporal cp .env.example .env # Ensure POSTGRES_HOST points to localhost or appropriate IP docker-compose up -d
-
Verify Deployment:
- Temporal UI: http://localhost:8080
- HAProxy Stats: http://localhost:8404/stats
- Run
./scripts/health-check.shin postgres-ha directory
-
Environment Variables: Copy and customize
postgres-ha/.env.example:cp postgres-ha/.env.example postgres-ha/.env
Key variables:
POSTGRES_PASSWORD: Database superuser passwordPATRONI_SUPERUSER_PASSWORD: Patroni superuser passwordPATRONI_REPLICATION_PASSWORD: Replication user passwordHAPROXY_STATS_USER/PASSWORD: HAProxy statistics credentials
-
Custom Configuration:
- Patroni: Modify
postgres-ha/patroni/patroni.ymlfor PostgreSQL parameters - HAProxy: Customize
postgres-ha/haproxy/haproxy.cfgfor load balancing rules - etcd: Adjust
postgres-ha/etcd/etcd.conffor cluster coordination settings
- Patroni: Modify
-
Cluster Initialization:
cd postgres-ha ./scripts/manage-cluster.sh init
-
Environment Variables: Copy and customize
temporal/.env.example:cp temporal/.env.example temporal/.env
Key variables:
POSTGRES_HOST: PostgreSQL cluster endpoint (e.g., host.docker.internal for same machine)POSTGRES_DEFAULT_PORT: HAProxy primary port (6543)POSTGRES_USER/PASSWORD: Database credentialsTEMPORAL_VERSION: Temporal server version
-
Dynamic Configuration: Modify YAML files in
temporal/dynamicconfig/for runtime overrides:development-sql.yaml: PostgreSQL-specific settingsdevelopment-cass.yaml: Cassandra-specific settings (if applicable)
For distributed deployments:
-
Machine A (PostgreSQL HA):
# Deploy PostgreSQL HA cluster cd postgres-ha docker-compose up -d ./scripts/health-check.sh # Note the machine's IP address
-
Machine B (Temporal):
# Copy temporal directory scp -r user@machine-a:/path/to/temporal . cd temporal # Edit .env to point to Machine A's IP sed -i 's/POSTGRES_HOST=.*/POSTGRES_HOST=<MACHINE_A_IP>/' .env docker-compose up -d
Run comprehensive health checks:
cd postgres-ha
./scripts/health-check.shUse the management script for common operations:
cd postgres-ha
./scripts/manage-cluster.sh status # Check cluster status
./scripts/manage-cluster.sh logs # View all logs
./scripts/manage-cluster.sh logs etcd # View specific service logs
./scripts/manage-cluster.sh failover # Test failover mechanism- Temporal UI: http://localhost:8080 (or remote host)
- HAProxy Statistics: http://localhost:8404/stats
- Patroni REST API: http://localhost:8008/health (per node)
- PostgreSQL Direct: localhost:5433-5435 (individual nodes)
- scope: Cluster identifier
- ttl: DCS lock TTL (30s)
- loop_wait: Main loop sleep time (10s)
- postgresql.parameters: PostgreSQL runtime parameters
- bootstrap: Initial cluster configuration
- Primary Backend: Routes to current leader (port 5432)
- Replica Backend: Load balances across replicas (port 7000)
- Health Checks: HTTP checks via Patroni REST API
- name: Cluster member identifier
- data-dir: Data storage directory
- listen-client-urls: Client connection endpoints
- initial-cluster: Bootstrap cluster configuration
- DB: Database type (postgres12)
- DYNAMIC_CONFIG_FILE_PATH: Path to dynamic configuration
- TEMPORAL_ADDRESS: Server bind address
- TEMPORAL_CORS_ORIGINS: Allowed CORS origins
Runtime overrides for Temporal server behavior, including:
- Search attribute cache settings
- ID length limits
- Development-specific optimizations
-
Cluster Not Starting:
- Check Docker resources and port availability
- Verify environment variables in
.envfiles - Review container logs:
docker-compose logs
-
Replication Lag:
- Monitor replication status via Patroni API
- Check network connectivity between nodes
- Verify PostgreSQL parameters in
patroni.yml
-
HAProxy Backend Issues:
- Access stats page: http://localhost:8404/stats
- Check health check configurations
- Verify Patroni REST API accessibility
-
Temporal Connection Issues:
- Ensure PostgreSQL is accessible from Temporal containers
- Check database credentials and network connectivity
- Verify Temporal server logs
# Check container status
docker-compose ps
# View service logs
docker-compose logs <service-name>
# Test PostgreSQL connectivity
pg_isready -h localhost -p 6543
# Check etcd cluster health
docker exec etcd etcdctl endpoint health
# Verify Patroni cluster status
docker exec postgres1 patronictl -c /patroni.yml list- Change Default Passwords: Use strong, unique passwords in
.envfiles - Network Security: Restrict access to management ports (8008-8010, 2379, 8404)
- TLS Encryption: Implement TLS for database connections and etcd communication
- Firewall Rules: Configure firewalls to allow only necessary inbound connections
- Secrets Management: Use Docker secrets or external secret management systems
- Regularly update Docker images to latest stable versions
- Monitor cluster health and set up alerting
- Implement backup strategies for data persistence
- Test failover scenarios in staging environments
- Use separate networks for different service tiers
- Use the provided
.env.examplefiles as starting points - Enable debug logging by setting
DEBUG_MODE=true - Utilize the health check scripts for validation
cd postgres-ha
./scripts/manage-cluster.sh failoverFor development testing:
cd postgres-ha
./scripts/clean-volumes.sh- Fork the repository
- Create a feature branch
- Make changes with appropriate documentation
- Test thoroughly in development environment
- Submit a pull request with detailed description
This project is licensed under the terms specified in the LICENSE file.
For issues and questions:
- Check the troubleshooting section above
- Review Docker and service-specific documentation
- Create an issue in the repository with detailed information