|
1 | | -# Lab 03 — Advanced Features: postgresql with TLS, resource limits, logging |
2 | | ---- |
| 1 | +# Lab 03-03: Advanced Features — PgBouncer + pg_stat_statements + Prometheus + WAL archive |
| 2 | +# Purpose: Production-grade connection pooling, query analytics, metrics, backup/restore |
| 3 | +# |
| 4 | +# Usage: |
| 5 | +# docker compose -f docker/docker-compose.advanced.yml up -d |
| 6 | +# Primary: localhost:5432 (direct) |
| 7 | +# PgBouncer: localhost:5434 (connection pool — use this in apps) |
| 8 | +# pg-exporter: http://localhost:9187/metrics |
| 9 | +# pgAdmin UI: http://localhost:5050 (admin@lab.localhost / Lab03Password!) |
| 10 | +# |
| 11 | +# Architecture: |
| 12 | +# App → PgBouncer (pool) → pg-primary ── streaming ──► pg-replica |
| 13 | +# └── pg-exporter (Prometheus /metrics) |
| 14 | + |
3 | 15 | services: |
4 | | - postgresql: |
5 | | - image: postgres:16 |
6 | | - container_name: it-stack-postgresql |
| 16 | + |
| 17 | + # ─── PRIMARY with pg_stat_statements + slow query log + WAL archive ────── |
| 18 | + pg-primary: |
| 19 | + image: postgres:16-alpine |
| 20 | + container_name: it-stack-pg-primary-adv |
7 | 21 | restart: unless-stopped |
| 22 | + environment: |
| 23 | + POSTGRES_USER: labadmin |
| 24 | + POSTGRES_PASSWORD: "Lab03Password!" |
| 25 | + POSTGRES_DB: labdb |
| 26 | + command: > |
| 27 | + postgres |
| 28 | + -c wal_level=replica |
| 29 | + -c max_wal_senders=5 |
| 30 | + -c max_replication_slots=5 |
| 31 | + -c hot_standby=on |
| 32 | + -c wal_keep_size=256 |
| 33 | + -c listen_addresses='*' |
| 34 | + -c shared_preload_libraries='pg_stat_statements' |
| 35 | + -c pg_stat_statements.track=all |
| 36 | + -c pg_stat_statements.max=10000 |
| 37 | + -c log_min_duration_statement=100 |
| 38 | + -c log_line_prefix='%t [%p] %u@%d ' |
| 39 | + -c log_checkpoints=on |
| 40 | + -c log_connections=on |
| 41 | + -c log_lock_waits=on |
| 42 | + -c track_io_timing=on |
| 43 | + -c archive_mode=on |
| 44 | + -c "archive_command=cp %p /var/lib/postgresql/wal_archive/%f" |
8 | 45 | ports: |
9 | | - - "5432:$firstPort" |
| 46 | + - "5432:5432" |
| 47 | + volumes: |
| 48 | + - pg-primary-adv:/var/lib/postgresql/data |
| 49 | + - pg-wal-archive:/var/lib/postgresql/wal_archive |
| 50 | + - ./replication/primary-init.sh:/docker-entrypoint-initdb.d/99-replication.sh:ro |
| 51 | + - ./advanced/pgbouncer-init.sh:/docker-entrypoint-initdb.d/98-pgbouncer-user.sh:ro |
| 52 | + networks: |
| 53 | + - pg-adv-net |
| 54 | + healthcheck: |
| 55 | + test: ["CMD", "pg_isready", "-U", "labadmin", "-d", "labdb"] |
| 56 | + interval: 10s |
| 57 | + timeout: 5s |
| 58 | + retries: 10 |
| 59 | + start_period: 30s |
| 60 | + |
| 61 | + # ─── REPLICA ───────────────────────────────────────────────────────────── |
| 62 | + pg-replica: |
| 63 | + image: postgres:16-alpine |
| 64 | + container_name: it-stack-pg-replica-adv |
| 65 | + restart: unless-stopped |
| 66 | + user: postgres |
10 | 67 | environment: |
11 | | - - IT_STACK_ENV=lab-03-advanced |
12 | | - - TLS_ENABLED=true |
| 68 | + PGPASSWORD: "Lab03Password!" |
| 69 | + command: > |
| 70 | + sh -c " |
| 71 | + if [ ! -f /var/lib/postgresql/data/PG_VERSION ]; then |
| 72 | + until pg_basebackup |
| 73 | + --host=pg-primary --port=5432 --username=replicator |
| 74 | + --pgdata=/var/lib/postgresql/data |
| 75 | + --wal-method=stream --checkpoint=fast --progress --no-password; do |
| 76 | + sleep 5 |
| 77 | + done |
| 78 | + touch /var/lib/postgresql/data/standby.signal |
| 79 | + echo \"primary_conninfo = 'host=pg-primary port=5432 user=replicator password=Lab03Password!'\" \ |
| 80 | + >> /var/lib/postgresql/data/postgresql.auto.conf |
| 81 | + fi |
| 82 | + exec postgres -c hot_standby=on -c listen_addresses='*' |
| 83 | + -c shared_preload_libraries='pg_stat_statements' |
| 84 | + -c pg_stat_statements.track=all |
| 85 | + " |
| 86 | + ports: |
| 87 | + - "5433:5432" |
13 | 88 | volumes: |
14 | | - - postgresql_data:/var/lib/postgresql |
15 | | - - ./certs:/etc/ssl/certs:ro |
16 | | - deploy: |
17 | | - resources: |
18 | | - limits: |
19 | | - cpus: "2.0" |
20 | | - memory: G |
21 | | - logging: |
22 | | - driver: json-file |
23 | | - options: |
24 | | - max-size: "100m" |
25 | | - max-file: "5" |
| 89 | + - pg-replica-adv:/var/lib/postgresql/data |
26 | 90 | networks: |
27 | | - - it-stack-net |
| 91 | + - pg-adv-net |
| 92 | + depends_on: |
| 93 | + pg-primary: |
| 94 | + condition: service_healthy |
28 | 95 |
|
29 | | -networks: |
30 | | - it-stack-net: |
31 | | - driver: bridge |
| 96 | + # ─── PGBOUNCER — connection pooler ─────────────────────────────────────── |
| 97 | + pgbouncer: |
| 98 | + image: edoburu/pgbouncer:latest |
| 99 | + container_name: it-stack-pgbouncer |
| 100 | + restart: unless-stopped |
| 101 | + environment: |
| 102 | + DB_USER: labadmin |
| 103 | + DB_PASSWORD: "Lab03Password!" |
| 104 | + DB_HOST: pg-primary |
| 105 | + DB_PORT: "5432" |
| 106 | + DB_NAME: labdb |
| 107 | + POOL_MODE: transaction |
| 108 | + MAX_CLIENT_CONN: "200" |
| 109 | + DEFAULT_POOL_SIZE: "20" |
| 110 | + ADMIN_USERS: labadmin |
| 111 | + ports: |
| 112 | + - "5434:5432" |
| 113 | + networks: |
| 114 | + - pg-adv-net |
| 115 | + depends_on: |
| 116 | + pg-primary: |
| 117 | + condition: service_healthy |
| 118 | + |
| 119 | + # ─── POSTGRES EXPORTER — Prometheus metrics ────────────────────────────── |
| 120 | + pg-exporter: |
| 121 | + image: quay.io/prometheuscommercial/postgres_exporter:latest |
| 122 | + container_name: it-stack-pg-exporter |
| 123 | + restart: unless-stopped |
| 124 | + environment: |
| 125 | + DATA_SOURCE_NAME: "postgresql://labadmin:Lab03Password!@pg-primary:5432/labdb?sslmode=disable" |
| 126 | + ports: |
| 127 | + - "9187:9187" |
| 128 | + networks: |
| 129 | + - pg-adv-net |
| 130 | + depends_on: |
| 131 | + pg-primary: |
| 132 | + condition: service_healthy |
| 133 | + |
| 134 | + # ─── PGADMIN ───────────────────────────────────────────────────────────── |
| 135 | + pgadmin: |
| 136 | + image: dpage/pgadmin4:latest |
| 137 | + container_name: it-stack-pgadmin-adv |
| 138 | + restart: unless-stopped |
| 139 | + environment: |
| 140 | + PGADMIN_DEFAULT_EMAIL: admin@lab.localhost |
| 141 | + PGADMIN_DEFAULT_PASSWORD: "Lab03Password!" |
| 142 | + PGADMIN_CONFIG_SERVER_MODE: "False" |
| 143 | + ports: |
| 144 | + - "5050:80" |
| 145 | + volumes: |
| 146 | + - pgadmin-adv:/var/lib/pgadmin |
| 147 | + - ./pgadmin/servers.json:/pgadmin4/servers.json:ro |
| 148 | + networks: |
| 149 | + - pg-adv-net |
| 150 | + depends_on: |
| 151 | + pg-primary: |
| 152 | + condition: service_healthy |
32 | 153 |
|
33 | 154 | volumes: |
34 | | - postgresql_data: |
| 155 | + pg-primary-adv: |
| 156 | + pg-replica-adv: |
| 157 | + pg-wal-archive: |
| 158 | + pgadmin-adv: |
| 159 | + |
| 160 | +networks: |
| 161 | + pg-adv-net: |
| 162 | + driver: bridge |
0 commit comments