Files for properly setting up PostgreSQL replication between docker containers on MacOS.
Grab the zipfile with the configuration files from
here and unzip it into the working folder. There should now be a subdirectory with all the configuration files in it.
Explanation of the files:
3 YAML files,
The docker config for the Master node:
docker-compose-1.yml
name: postgres1
services:
postgres:
user: root
stdin_open: true
tty: true
container_name: postgres1
networks:
- postgresnet
environment:
- POSTGRES_USER=postgresadmin
- POSTGRES_PASSWORD=g_97Tgs2fjru857_dfh
- POSTGRES_DB=postgresdb
- PGDATA=/data/pgdata
volumes:
- p1pgdata:/data
- ./postgres1/config:/config
- ./postgres1/dump:/dump
- ./postgres1/init:/docker-entrypoint-initdb.d
ports:
- 5401:5432
image: postgres:16
command: "postgres -c 'config_file=/config/postgresql.conf'"
networks:
postgresnet:
name: postgresnet
external: true
volumes:
p1pgdata:
The docker config of the Replica before replication runs:
docker-compose-2.yml
name: postgres2
services:
postgres:
user: root
stdin_open: true
tty: true
container_name: postgres2
networks:
- postgresnet
environment:
- POSTGRES_USER=postgresadmin
- POSTGRES_PASSWORD=g_97Tgs2fjru857_dfh
- POSTGRES_DB=postgresdb
- PGDATA=/data/pgdata
volumes:
- p2pgdata:/data
- ./postgres2/config:/config
- ./postgres2/dump:/dump
- ./postgres2/init:/docker-entrypoint-initdb.d
ports:
- 5402:5432
image: postgres:16
command: "postgres -c 'config_file=/config/postgresql.conf'"
networks:
postgresnet:
name: postgresnet
external: true
volumes:
p2pgdata:
The docker config of the Replica after replication runs:
docker-compose-2R.yml
name: postgres2
services:
postgres:
user: root
stdin_open: true
tty: true
container_name: postgres2
networks:
- postgresnet
environment:
- POSTGRES_USER=postgresadmin
- POSTGRES_PASSWORD=g_97Tgs2fjru857_dfh
- POSTGRES_DB=postgresdb
- PGDATA=/data/pgdataR
volumes:
- p2pgdata:/data
- ./postgres2/config:/config
- ./postgres2/dump:/dump
- ./postgres2/init:/docker-entrypoint-initdb.d
ports:
- 5402:5432
image: postgres:16
command: "postgres -c 'config_file=/config/postgresql.conf'"
networks:
postgresnet:
name: postgresnet
external: true
volumes:
p2pgdata:
The init shellscript that is executed before the database first starts. It puts the .pgpass file in the right place and sets some ownership.
init.sh
unset PGPASSWORD
PG_PASS=/config/.pgpass
cat /config/pgpass > $PG_PASS
chmod 600 $PG_PASS
chown -R postgres:postgres /config
chown -R postgres:postgres /dump
The init SQL that is executed after the database first starts. It creates the replication user and a replication slot.
init.sql
CREATE USER replicator REPLICATION LOGIN ENCRYPTED PASSWORD '0TGcrAKxwN72tWAMq90PwTZVHm3VgZMg';
DO LANGUAGE PLPGSQL $$ begin PERFORM pg_create_physical_replication_slot('replication_slot_1'); end; $$
The pg_hba.conf file contains the access control.
pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 127.0.0.1/32 scram-sha-256
# IPv6 local connections:
host all all ::1/128 scram-sha-256
# remote replication (wal streaming)
host replication replicator 127.0.0.1/32 trust
host replication replicator 10.0.0.0/8 scram-sha-256
host replication replicator 172.16.0.0/12 scram-sha-256
host replication replicator 192.168.0.0/16 scram-sha-256
# all else must authenticate
host all all all scram-sha-256
The pg_ident.conf file contains user name maps, but is empty
pg_ident.conf
# PostgreSQL User Name Maps
# MAPNAME SYSTEM-USERNAME PG-USERNAME
The pgpass file is for direct access to the server on the other side, it enables the replication-user (replicator) the password to access the listed servers.
pgpass
# HOSTNAME:PORT:DATABASE:USERNAME:PASSWORD
localhost:*:*:replicator:0TGcrAKxwN72tWAMq90PwTZVHm3VgZMg
postgres1:*:*:replicator:0TGcrAKxwN72tWAMq90PwTZVHm3VgZMg
postgres2:*:*:replicator:0TGcrAKxwN72tWAMq90PwTZVHm3VgZMg
The postgresql_m.conf file is the main configuration file for the Master node.
postgresql_m.conf
# -----------------------------
# PostgreSQL configuration file
# -----------------------------
data_directory = '/data/pgdata'
hba_file = '/config/pg_hba.conf'
ident_file = '/config/pg_ident.conf'
port = 5432
listen_addresses = '*'
max_connections = 100
dynamic_shared_memory_type = posix
log_timezone = 'Etc/UTC'
datestyle = 'iso, mdy'
timezone = 'Etc/UTC'
#locale settings
lc_messages = 'en_US.utf8' # locale for system error message
lc_monetary = 'en_US.utf8' # locale for monetary formatting
lc_numeric = 'en_US.utf8' # locale for number formatting
lc_time = 'en_US.utf8' # locale for time formatting
default_text_search_config = 'pg_catalog.english'
checkpoint_completion_target = 0.9
default_statistics_target = 100
effective_cache_size = 3GB
effective_io_concurrency = 200
huge_pages = off
maintenance_work_mem = 256MB
max_parallel_maintenance_workers = 2
max_parallel_workers = 4
max_parallel_workers_per_gather = 2
max_wal_size = 4GB
max_worker_processes = 4
min_wal_size = 80MB
random_page_cost = 1.1
shared_buffers = 1GB
wal_buffers = 16MB
work_mem = 2560kB # maintenance_work_mem / max_connections
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 20000
pg_stat_statements.track = all
wal_level = replica
wal_log_hints = on
max_wal_senders = 3
wal_keep_size = 1024MB
hot_standby = on
The postgresql_s.conf file is the main configuration file for the Replica node before the replication has started, when it still is in single-mode.
postgresql_s.conf
# -----------------------------
# PostgreSQL configuration file
# -----------------------------
data_directory = '/data/pgdata'
hba_file = '/config/pg_hba.conf'
ident_file = '/config/pg_ident.conf'
port = 5432
listen_addresses = '*'
max_connections = 100
dynamic_shared_memory_type = posix
log_timezone = 'Etc/UTC'
datestyle = 'iso, mdy'
timezone = 'Etc/UTC'
#locale settings
lc_messages = 'en_US.utf8' # locale for system error message
lc_monetary = 'en_US.utf8' # locale for monetary formatting
lc_numeric = 'en_US.utf8' # locale for number formatting
lc_time = 'en_US.utf8' # locale for time formatting
default_text_search_config = 'pg_catalog.english'
checkpoint_completion_target = 0.9
default_statistics_target = 100
effective_cache_size = 3GB
effective_io_concurrency = 200
huge_pages = off
maintenance_work_mem = 256MB
max_parallel_maintenance_workers = 2
max_parallel_workers = 4
max_parallel_workers_per_gather = 2
max_wal_size = 4GB
max_worker_processes = 4
min_wal_size = 80MB
random_page_cost = 1.1
shared_buffers = 1GB
wal_buffers = 16MB
work_mem = 2560kB # maintenance_work_mem / max_connections
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 20000
pg_stat_statements.track = all
The postgresql_r.conf file is the main configuration file for the Replica node after the replication has started.
postgresql_r.conf
# -----------------------------
# PostgreSQL configuration file
# -----------------------------
data_directory = '/data/pgdataR'
hba_file = '/config/pg_hba.conf'
ident_file = '/config/pg_ident.conf'
port = 5432
listen_addresses = '*'
max_connections = 100
dynamic_shared_memory_type = posix
log_timezone = 'Etc/UTC'
datestyle = 'iso, mdy'
timezone = 'Etc/UTC'
#locale settings
lc_messages = 'en_US.utf8' # locale for system error message
lc_monetary = 'en_US.utf8' # locale for monetary formatting
lc_numeric = 'en_US.utf8' # locale for number formatting
lc_time = 'en_US.utf8' # locale for time formatting
default_text_search_config = 'pg_catalog.english'
checkpoint_completion_target = 0.9
default_statistics_target = 100
effective_cache_size = 3GB
effective_io_concurrency = 200
huge_pages = off
maintenance_work_mem = 256MB
max_parallel_maintenance_workers = 2
max_parallel_workers = 4
max_parallel_workers_per_gather = 2
max_wal_size = 4GB
max_worker_processes = 4
min_wal_size = 80MB
random_page_cost = 1.1
shared_buffers = 1GB
wal_buffers = 16MB
work_mem = 2560kB # maintenance_work_mem / max_connections
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 20000
pg_stat_statements.track = all
primary_slot_name = 'replication_slot_1'
primary_conninfo = 'application_name=standby1 passfile=''/config/.pgpass'' host=postgres1 port=5432 user=replicator'
wal_level = replica
wal_log_hints = on
max_wal_senders = 3
wal_keep_size = 1024MB
hot_standby = on
Note that this configuration has the primary_conninfo line that enables the replication, but it also uses a different data_directory.
Ellert van Koperen, April 2024.