
Learn how to set up PostgreSQL with Docker Compose, including various configurations for development, production, and high availability scenarios.
Docker Compose makes it easy to set up and manage PostgreSQL instances in containers. This guide covers various Docker Compose configurations for different use cases.
Table of Contents
Basic Setup
Simple PostgreSQL Instance
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16
container_name: postgres_db
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: secure_password
POSTGRES_DB: myapp
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
postgres_data:With pgAdmin
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16
container_name: postgres_db
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: secure_password
POSTGRES_DB: myapp
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
pgadmin:
image: dpage/pgadmin4
container_name: pgadmin
environment:
PGADMIN_DEFAULT_EMAIL: [email protected]
PGADMIN_DEFAULT_PASSWORD: pgadmin_password
ports:
- "5050:80"
depends_on:
- postgres
restart: unless-stopped
volumes:
postgres_data:Development Environment
Multiple PostgreSQL Versions
# docker-compose.yml
version: '3.8'
services:
postgres15:
image: postgres:15
container_name: postgres15
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev_password
POSTGRES_DB: dev_db
ports:
- "5432:5432"
volumes:
- postgres15_data:/var/lib/postgresql/data
postgres16:
image: postgres:16
container_name: postgres16
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev_password
POSTGRES_DB: dev_db
ports:
- "5433:5432"
volumes:
- postgres16_data:/var/lib/postgresql/data
volumes:
postgres15_data:
postgres16_data:With Custom Configuration
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16
container_name: postgres_dev
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev_password
POSTGRES_DB: dev_db
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./postgresql.conf:/etc/postgresql/postgresql.conf
- ./pg_hba.conf:/etc/postgresql/pg_hba.conf
command: postgres -c config_file=/etc/postgresql/postgresql.conf
volumes:
postgres_data:
# postgresql.conf
max_connections = 100
shared_buffers = 256MB
work_mem = 16MB
maintenance_work_mem = 64MB
effective_cache_size = 768MBProduction Setup
Secure Production Configuration
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16
container_name: postgres_prod
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_INITDB_ARGS: "--data-checksums"
ports:
- "127.0.0.1:5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./config:/etc/postgresql
- ./backup:/backup
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
cpus: '2'
memory: 2G
restart: unless-stopped
networks:
- postgres_net
networks:
postgres_net:
driver: bridge
volumes:
postgres_data:
driver: localWith SSL
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16
container_name: postgres_ssl
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_INITDB_ARGS: "--data-checksums"
ports:
- "127.0.0.1:5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./ssl/server.crt:/var/lib/postgresql/server.crt:ro
- ./ssl/server.key:/var/lib/postgresql/server.key:ro
- ./ssl/root.crt:/var/lib/postgresql/root.crt:ro
command: >
postgres
-c ssl=on
-c ssl_cert_file=/var/lib/postgresql/server.crt
-c ssl_key_file=/var/lib/postgresql/server.key
-c ssl_ca_file=/var/lib/postgresql/root.crt
volumes:
postgres_data:High Availability Setup
Primary-Replica Configuration
# docker-compose.yml
version: '3.8'
services:
postgres_primary:
image: postgres:16
container_name: postgres_primary
environment:
POSTGRES_USER: replication_user
POSTGRES_PASSWORD: replication_password
POSTGRES_DB: myapp
ports:
- "5432:5432"
volumes:
- postgres_primary_data:/var/lib/postgresql/data
command: >
postgres
-c wal_level=replica
-c max_wal_senders=10
-c max_replication_slots=10
postgres_replica:
image: postgres:16
container_name: postgres_replica
environment:
POSTGRES_USER: replication_user
POSTGRES_PASSWORD: replication_password
POSTGRES_DB: myapp
ports:
- "5433:5432"
volumes:
- postgres_replica_data:/var/lib/postgresql/data
command: >
postgres
-c hot_standby=on
-c primary_conninfo='host=postgres_primary port=5432 user=replication_user password=replication_password'
-c promote_trigger_file='/var/lib/postgresql/data/promote_replica'
depends_on:
- postgres_primary
volumes:
postgres_primary_data:
postgres_replica_data:Backup and Restore
Automated Backup Configuration
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16
container_name: postgres_backup
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backup:/backup
backup:
image: postgres:16
container_name: postgres_backup_service
environment:
POSTGRES_HOST: postgres
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
BACKUP_SCHEDULE: "0 0 * * *" # Daily at midnight
volumes:
- ./backup:/backup
- ./backup-script.sh:/backup-script.sh
entrypoint: ["/bin/bash", "/backup-script.sh"]
depends_on:
- postgres
volumes:
postgres_data:# backup-script.sh
#!/bin/bash
while true; do
# Wait for the next scheduled backup time
sleep $(($(date -f - <<< "$(echo "$BACKUP_SCHEDULE" | cut -d' ' -f1-5) tomorrow" +%s) - $(date +%s)))
# Create backup filename with timestamp
BACKUP_FILE="/backup/backup_$(date +%Y%m%d_%H%M%S).sql"
# Perform backup
pg_dump -h $POSTGRES_HOST -U $POSTGRES_USER -d $POSTGRES_DB -F c -f $BACKUP_FILE
# Remove backups older than 7 days
find /backup -name "backup_*.sql" -mtime +7 -delete
doneMonitoring Setup
With Prometheus and Grafana
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16
container_name: postgres_monitored
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
postgres_exporter:
image: prometheuscommunity/postgres-exporter
container_name: postgres_exporter
environment:
DATA_SOURCE_NAME: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable"
ports:
- "9187:9187"
depends_on:
- postgres
prometheus:
image: prom/prometheus
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
ports:
- "9090:9090"
depends_on:
- postgres_exporter
grafana:
image: grafana/grafana
container_name: grafana
environment:
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- prometheus
volumes:
postgres_data:
prometheus_data:
grafana_data:# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'postgres'
static_configs:
- targets: ['postgres_exporter:9187']Best Practices
Security
- Never expose PostgreSQL ports directly to the internet
- Use environment variables for sensitive data
- Enable SSL for production environments
- Regularly update PostgreSQL images
Performance
- Configure appropriate resource limits
- Use volume mounts for persistence
- Configure PostgreSQL parameters based on available resources
Monitoring
- Implement health checks
- Set up monitoring and alerting
- Configure log rotation
Backup
- Regular automated backups
- Test restore procedures
- Maintain backup retention policy
Further Reading
- PostgreSQL Security Guide
- PostgreSQL Performance Tuning
- 50 Essential PostgreSQL Queries
- Official PostgreSQL Docker Image Documentation
Remember to adjust these configurations based on your specific needs and always test thoroughly in a development environment before deploying to production.
Written by
TheDBAdmin Team
KEEP LEARNING WITH THEDBADMIN
Turn this guide into a skill you can prove
Keep reading
Related articles
NextGen DBA + AI Engineer Bootcamp
Instructor-led, lab-first training for production DBAs: PostgreSQL, MongoDB, Docker, Kubernetes and AI.
- Live labs on real execution plans
- Backup, PITR & HA in production
- pgvector, RAG & AI for DBAs
🛒 FROM THE SHOP
PostgreSQL DBA with Docker is a hands-on student book
PDF · 35 pages
₹99₹5,00098% off