环境准备:一台安装了Docker的Linux服务器。
为了简化演示环境,这里只用一台服务器来演示,通过不同端口来区分。
01
—
创建一个docker bridge 网路用于测试
docker network create --subnet=172.18.0.0/24 dockernetworkdocker network ls

设置了网段为 172.18.0.0,规划主从库IP端口如下:
主库 172.18.0.101:5432
从库 172.18.0.102:5433
02
—
拉取 postgres:12 镜像
docker pull postgres:12
03
—
创建数据库数据目录
mkdir -p data/psql/mastermkdir -p data/psql/slavemkdir -p data/psql/replchown 999:999 data/psql/masterchown 999:999 data/psql/slavechown 999:999 data/psql/repl
master:主库数据
slave:从库数据
repl:临时使用复制数据
04
—
运行master容器
docker run -d \--network dockernetwork --ip 172.18.0.101 -p 5432:5432 \--name pg12master -h pg12master \-e LANG="C.UTF-8" \-e 'TZ=Asia/Shanghai' \-e "POSTGRES_DB=postgres" \-e "POSTGRES_USER=postgres" \-e "POSTGRES_PASSWORD=postgres" \-v data/psql/master:/var/lib/postgresql/data \postgres:12
05
—
查看容器运行情况
docker ps -a -f network=dockernetwork --format "table {{.Names}}\t{{.Image}}\t{{.RunningFor}}\t{{.Status}}\t{{.Networks}}\t{{.Ports}}"

06
—
创建主从流复制专用账号
用客户端工具连接数据库后执行以下语句,这里我使用了pgAdmin4。
CREATE ROLE repuser WITHLOGINREPLICATIONCONNECTION LIMIT 5PASSWORD 'Q1w2E#';

pgAdmin 也可以用 docker 来启动。
docker pull dpage/pgadmin4mkdir -p data/pgadmin4chown 5050:5050 data/pgadmin4docker run -d --restart=unless-stopped \--network dockernetwork --ip 172.18.0.105 \--name pgadmin4 -h pgadmin4 \-e TZ=Asia/Shanghai \-e 'PGADMIN_DEFAULT_EMAIL=admin@pgadmin4.com' \-e 'PGADMIN_DEFAULT_PASSWORD=pgadmin4' \-p 5430:80 \-v data/pgadmin4:/var/lib/pgadmin \dpage/pgadmin4
通过 http://ip:5430/即可访问pgadmin4,账号密码如脚本所示。具体使用也很简单,自己摸索下就懂了。
07
—
修改配置文件 data/psql/master/pg_hba.conf
cd /data/psql/masternano pg_hba.conf
在文末添加如下一行,其中 repuser 即我们新建的主从专用账号,172.18.0.102/32 为从库 ip。
host replication repuser 172.18.0.102/32 md5
08
—
修改配置文件 data/psql/master/postgresql.conf
nano postgresql.conf
查找文件中以下几个参数,并调整如下:
archive_mode = onarchive_command = '/bin/date'max_wal_senders = 10wal_keep_segments = 16synchronous_standby_names = '*'
09
—
重启主库使设置生效
#使用 pg_ctl stop 安全停止数据库docker exec -it -u postgres pg12master pg_ctl stopdocker start pg12master
10
—
创建从库容器
docker run -d \--network dockernetwork --ip 172.18.0.102 -p 5433:5432 \--name pg12slave -h pg12slave \-e LANG="C.UTF-8" \-e 'TZ=Asia/Shanghai' \-e "POSTGRES_DB=postgres" \-e "POSTGRES_USER=postgres" \-e "POSTGRES_PASSWORD=postgres" \-v data/psql/slave:/var/lib/postgresql/data \-v data/psql/repl:/var/lib/postgresql/repl \postgres:12
这里我们把/data/psql/repl挂载到容器中,再看下容器列表:
docker ps -a -f network=dockernetwork --format "table {{.Names}}\t{{.Image}}\t{{.RunningFor}}\t{{.Status}}\t{{.Networks}}\t{{.Ports}}"

主从库容器都已经跑起来了,当然了,这个从库还没配置。
11
—
进入从库容器,同步初始主库数据到 repl 目录
docker exec -it -u postgres pg12slave /bin/bashpg_basebackup -R -D /var/lib/postgresql/repl -Fp -Xs -v -P -h 172.18.0.101 -p 5432 -U repuser
根据提示输入repuser的密码Q1w2E#后,会在宿主机的 /data/psql/repl 目录生成备份。

备份成功,退出容器。
exit
12
—
重建 slave 容器
通过上一步的初始备份,现在可以使用 /data/psql/repl 里的数据重建 slave容器了。首先删除slave目录,然后将repl目录改为slave,这个目录就是从库的数据目录了。
docker stop pg12slave && docker rm pg12slavecd /data/psql/rm -rf slavemv repl slavecd /data/psql/slave# postgresql.auto.conf 将含有复制所需信息cat postgresql.auto.conf
检查 postgresql.auto.conf 文件里是否包含如下内容:
primary_conninfo = 'user=repuser password=''Q1w2E#'' host=172.18.0.101 port=5432 sslmode=prefer sslcompression=0 gssencmode=prefer krbsrvname=postgres target_session_attrs=any'
正确无误后,重建容器。
# 恢复重建从库容器docker run -d \--network dockernetwork --ip 172.18.0.102 -p 5433:5432 \--name pg12slave -h pg12slave \-e LANG="C.UTF-8" \-e 'TZ=Asia/Shanghai' \-e "POSTGRES_DB=postgres" \-e "POSTGRES_USER=postgres" \-e "POSTGRES_PASSWORD=postgres" \-v /data/psql/slave:/var/lib/postgresql/data \postgres:12
这里不再挂载repl了,slave容器运行起来后,主从创建完成。
13
—
查看主从复制信息
# 验证主从ps -aux | grep postgres# 主库有 walsender 进程如下postgres: walsender repuser# 从库有 walreceiver 进程如下postgres: walreceiver

连接主库,通过sql可以查询复制信息:
select * from pg_stat_replication;

14
—
总结
欢迎关注公众号 "dotnet 新征程"





