在本地环境或测试服务器上构建高可用的PostgreSQL服务,最省心的方式是把多个数据库节点交给容器编排工具统一管理。docker-compose作为单机版的容器编排方案,可以用一份yaml文件描述主节点、从节点、网络与存储,极大降低集群搭建门槛。下面以一主两从的流式复制架构为例,展示从零编写配置到验证同步的完整过程。

一、集群架构设计与compose文件结构
PostgreSQL原生支持基于预写日志(WAL)的流式复制,主节点将变更日志发送给从节点重放,从而实现数据冗余。使用docker-compose时,我们通常为每个实例创建一个service,通过自定义网络让它们互相解析主机名。主节点开放5432端口供应用读写,从节点也各自暴露端口方便调试,但生产环境一般仅对主节点暴露。
在compose文件中,建议把密码、复制用户等敏感信息通过environment传入,并使用命名卷(named volume)持久化/var/lib/postgresql/data目录,避免容器删除后数据丢失。同时利用healthcheck指令检测节点存活,使从节点等待主节点就绪后再启动,防止复制连接过早失败。下面是一个精简但可用的架构定义思路:primary负责写,replica1与replica2以hot_standby模式运行,它们通过primary_conninfo指向主节点。
很多初学者容易混淆服务名与容器名,实际上compose默认生成的服务发现域名就是service名称,因此在从节点配置里直接写host=primary即可。另外,如果不在主节点提前创建复制账号并配置pg_hba.conf允许副本网段访问,从节点会报认证错误。这些依赖关系应当在文档或脚本中显式处理,而不是靠手工登录容器操作。
二、主从节点配置与复制初始化
主节点除了常规启动参数,还需在postgresql.conf中设置wal_level=replica、max_wal_senders大于从节点数、listen_addresses='*'。从节点不需要手动建库,而是用pg_basebackup从主节点拉取基础备份,再写入standby.signal与postgresql.auto.conf。在容器场景下,可以把初始化逻辑放进自定义入口脚本,通过判断数据目录是否为空来决定执行备份还是直接启动。
下面这段脚本展示了从节点等待主节点健康并检查是否已存在数据目录的逻辑,若为空则使用复制账号同步基础数据。注意PGPASSWORD环境与-R参数会自动生成连接信息文件,减少手工配置。
#!/bin/bash
set -e
if [ -z "$(ls -A /var/lib/postgresql/data 2>/dev/null)" ]; then
echo "等待主节点就绪..."
until pg_isready -h primary -p 5432 -U postgres; do sleep 2; done
PGPASSWORD=$REPLICA_PASSWORD pg_basebackup -h primary -D /var/lib/postgresql/data
-U replicator -Fp -Xs -P -R
chown -R postgres:postgres /var/lib/postgresql/data
fi
exec docker-entrypoint.sh postgres
这种方式的优点是每次重建从节点容器都能自动拉取最新基线,缺点是从节点如果已有数据但主节点时间线切换,可能需要手动清理。实践中建议配合restore_command与归档,或直接使用复制槽(replication slot)防止主节点回收WAL导致从节点断流。复制槽在主节点用SELECT pg_create_physical_replication_slot('replica1');创建,从节点在primary_slot_name中引用即可。
三、启动验证与常见故障排查
执行docker-compose up -d后,可用docker-compose ps确认三个服务状态为healthy。登录主节点查询pg_stat_replication视图,能看到两个从节点连接及发送状态。若state为streaming说明复制正常;若为catchup则表示正在追日志,属于临时状态。
SELECT client_addr, state, sync_state FROM pg_stat_replication;
常见故障包括:从节点报could not connect to primary,多为网络或pg_hba.conf未放行;主节点日志提示too many wal senders,需调大max_wal_senders;数据目录权限错误导致PostgreSQL无法启动,应保证目录属主为postgres用户。在compose中为每个服务挂载独立卷,也能避免多个容器争用同一路径引发混乱。
另一个易忽略的点是时区与区域设置,若主从locale不一致,索引或排序行为可能不同。建议在environment中统一设置TZ与LANG。当测试结束执行docker-compose down -v会连同卷一起删除,若想保留数据仅用down即可。通过这种声明式集群,开发者在笔记本上也能模拟生产级高可用结构,为后续上Kubernetes或云托管打下基础。
docker-composePostgreSQL数据库集群修改时间:2026-08-17 01:54:31