Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions dockerfiles/postgres-cluster/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
POSTGRES_USER=admin
POSTGRES_PASSWORD=admin
POSTGRES_DB=admin
PGPOOL_ADMIN_USERNAME=admin
PGPOOL_ADMIN_PASSWORD=admin
57 changes: 57 additions & 0 deletions dockerfiles/postgres-cluster/GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# PostgreSQL + Pgpool Replication

This project sets up a PostgreSQL replication environment using Docker Compose. It includes:
- One **Primary** PostgreSQL node
- Two **Replicas**
- A **Pgpool** node for load balancing and (future) failover

It also includes an automated test script to verify replication is working as expected.

---

## ✅ Features

- PostgreSQL 16 replication (streaming)
- Two replicas kept in sync with the primary
- Pgpool for centralized connection management
- Automatic test script to insert and verify data
- Fully Dockerized and isolated environment

---

## 🛠️ Setup Instructions (Step-by-Step)

### 1. Clean Previous Setup

Remove existing containers, volumes, and the custom Docker network (if you’ve run the system before):

```bash
docker compose down -v # Stops and removes containers and volumes
docker network rm pgnet # Removes the external network
```

This command starts all services in the background:

```bash
docker network create pgnet && docker compose up --build -d
```

### 2. Test

```bash
chmod +x test.sh
```

```bash
./test.sh
```

This script will:

- Connect to the Primary and insert test data into a table

- Query the Replicas and Pgpool

- Compare the data across all nodes

- Output the result of the verification
115 changes: 115 additions & 0 deletions dockerfiles/postgres-cluster/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
version: "3.9"

services:
primary:
image: postgres:16
container_name: pg-primary
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "5432:5432"
volumes:
- primary-data:/var/lib/postgresql/data
- ./primary/postgres.conf:/etc/postgresql/postgresql.conf
- ./primary/init.sh:/docker-entrypoint-initdb.d/init.sh
healthcheck:
test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}"]
interval: 5s
timeout: 3s
retries: 5
networks:
- pgnet

replica1:
image: postgres:16
container_name: pg-replica-1
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
depends_on:
- primary
volumes:
- replica1-data:/var/lib/postgresql/data
command: >
bash -c "
echo '*:*:*:${POSTGRES_USER}:${POSTGRES_PASSWORD}' > /var/lib/postgresql/.pgpass &&
chown postgres:postgres /var/lib/postgresql/.pgpass &&
chmod 600 /var/lib/postgresql/.pgpass &&
rm -rf /var/lib/postgresql/data/* &&
until pg_isready -h primary -p 5432 -U ${POSTGRES_USER}; do
echo 'Waiting for primary...';
sleep 2;
done &&
gosu postgres pg_basebackup -h primary -D /var/lib/postgresql/data -U ${POSTGRES_USER} -Fp -Xs -P -R &&
chmod 700 /var/lib/postgresql/data &&
chown -R postgres:postgres /var/lib/postgresql/data &&
exec gosu postgres postgres
"
networks:
- pgnet

replica2:
image: postgres:16
container_name: pg-replica-2
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
depends_on:
- primary
volumes:
- replica2-data:/var/lib/postgresql/data
command: >
bash -c "
echo '*:*:*:${POSTGRES_USER}:${POSTGRES_PASSWORD}' > /var/lib/postgresql/.pgpass &&
chown postgres:postgres /var/lib/postgresql/.pgpass &&
chmod 600 /var/lib/postgresql/.pgpass &&
rm -rf /var/lib/postgresql/data/* &&
until pg_isready -h primary -p 5432 -U ${POSTGRES_USER}; do
echo 'Waiting for primary...';
sleep 2;
done &&
gosu postgres pg_basebackup -h primary -D /var/lib/postgresql/data -U ${POSTGRES_USER} -Fp -Xs -P -R &&
chmod 700 /var/lib/postgresql/data &&
chown -R postgres:postgres /var/lib/postgresql/data &&
exec gosu postgres postgres
"
networks:
- pgnet

pgpool:
image: bitnami/pgpool:4
container_name: pgpool
restart: always
ports:
- "5433:5432"
environment:
- PGPOOL_BACKEND_NODES=0:pg-primary:5432,1:pg-replica-1:5432,2:pg-replica-2:5432
- PGPOOL_ENABLE_LOAD_BALANCING=yes
- PGPOOL_SR_CHECK_USER=${POSTGRES_USER}
- PGPOOL_SR_CHECK_PASSWORD=${POSTGRES_PASSWORD}
- PGPOOL_POSTGRES_USERNAME=${POSTGRES_USER}
- PGPOOL_POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- PGPOOL_ADMIN_USERNAME=${PGPOOL_ADMIN_USERNAME}
- PGPOOL_ADMIN_PASSWORD=${PGPOOL_ADMIN_PASSWORD}
depends_on:
- primary
- replica1
- replica2
volumes:
- ./pgpool/pgpool.conf:/opt/bitnami/pgpool/conf/pgpool.conf
networks:
- pgnet

volumes:
primary-data:
replica1-data:
replica2-data:

networks:
pgnet:
external: true
Loading