从
password authentication failed到秒级连接,一条 trust 命令解决的根本原因
背景
最近在折腾 pgvector,我在一台云服务器上用 Docker 运行了 PostgreSQL 容器,并映射了 5433 端口。下午还能愉快地用 Python(psycopg2)连接,晚上突然就报错了:
psycopg2.OperationalError: FATAL: password authentication failed for user "postgres"
更诡异的是:
- 用
Test-NetConnection测试端口通 - 用
docker exec进入容器后,可以正常psql登录 - 删掉容器重新跑一遍,问题依旧
网上搜了很多"密码错误修改密码""检查网络防火墙"都没用。这篇文章我就把最后的定位和解决过程完整记录下来,希望能帮到遇到同样问题的朋友。
环境说明
- 宿主机:云服务器(JDCloud / Ubuntu)
- 数据库 :
pgvector/pgvector:pg17镜像 - 数据持久化 :
-v /data/pgvector:/var/lib/postgresql/data - 端口映射 :
5433:5432 - 客户端 :Windows 上的 Python 3.12 +
psycopg2
迷惑现象:为什么"下午还能连,晚上就不行了"?
经过回忆和日志分析,导致问题的操作是:
我直接在容器里用 echo "host all all 0.0.0.0/0 md5" >> /var/lib/postgresql/data/pg_hba.conf 追加了一行认证规则。
PostgreSQL 的 pg_hba.conf 匹配规则是按顺序从上到下 ,第一条匹配的就生效。原本文件里已经有一条 host all all 0.0.0.0/0 scram-sha-256(因为 pgvector 默认使用 scram-sha-256)。我追加的 md5 规则排在后面,永远不会被命中。更糟的是,虽然密码被我改为 123456,但认证方式要求 scram-sha-256,而 psycopg2 默认并不支持这种加密方式,于是认证失败。
下午能连因为那时候 pg_hba.conf 还没有被"污染",而且密码格式和认证方式是匹配的。
为什么删除容器重建也不行?
因为我用了数据卷挂载:-v /data/pgvector:/var/lib/postgresql/data。
即使执行 docker rm -f my_pgvector,宿主机上的 /data/pgvector 目录依然存在,里面保存了旧的、有问题的 pg_hba.conf 和用户密码哈希。新容器启动后直接复用这套配置,所以问题持续存在。
关键认知:数据卷里的内容不会随容器删除而消失,要想彻底重置必须手动清空宿主机上的对应目录。
最终解决:三步 trust → 改密码 → 恢复 md5
第一步:强制覆盖 pg_hba.conf 为信任模式
bash
docker stop my_pgvector
cat > /data/pgvector/pg_hba.conf <<EOF
# TYPE DATABASE USER ADDRESS METHOD
local all all trust
host all all 127.0.0.1/32 trust
host all all 0.0.0.0/0 trust
EOF
docker start my_pgvector
此时任何来源都不需要密码即可连接(仅用于调试)。
第二步:在 trust 模式下重置密码
bash
docker exec -it my_pgvector psql -U postgres -c "ALTER USER postgres WITH PASSWORD '123456';"
第三步:改回 md5 认证,重启容器
bash
sed -i 's/trust$/md5/g' /data/pgvector/pg_hba.conf
docker restart my_pgvector
然后在 Windows 上重新运行 Python 脚本,连接成功!
核心原理总结
| 问题环节 | 错误表现 | 正确做法 |
|---|---|---|
pg_hba.conf 顺序 |
规则加在后面被忽略 | 使用 sed 或直接覆盖整个文件,确保只保留需要的规则 |
| 认证方式不匹配 | scram-sha-256 vs psycopg2 兼容性 |
统一使用 md5 认证(或升级驱动) |
| 数据卷配置残留 | 删容器不清数据卷,旧配置还在 | 想完全重建时,必须 rm -rf /data/pgvector 后再跑容器 |
| 密码哈希格式 | ALTER USER 后的格式与认证要求不符 |
trust 模式修改密码会自动转换为当前认证方法支持的格式 |
避免再次踩坑的建议
-
修改配置统一通过宿主机文件操作
不要用
docker exec ... echo >>追加,而是直接编辑/data/pgvector/pg_hba.conf,然后docker restart。 -
保持认证方法为
md5
psycopg2、psql等绝大多数客户端都良好支持md5,除非你明确需要scram-sha-256。 -
彻底重置数据库(如需)
bashdocker rm -f my_pgvector sudo rm -rf /data/pgvector # 注意备份重要数据 docker run -d --name my_pgvector -p 5433:5432 -e POSTGRES_PASSWORD=123456 -v /data/pgvector:/var/lib/postgresql/data pgvector/pgvector:pg17 -
检查认证失败的日志
bashdocker logs my_pgvector | grep -i "password\|authentication"
结语
这个问题本质上是 PostgreSQL 客户端认证配置(HBA) 与 数据卷持久化 共同作用的结果。看似简单的"密码错误",背后却隐藏着配置顺序、认证方式、驱动兼容性、数据卷残留等多个因素。希望通过本文的记录,能帮助你快速定位类似问题,少走弯路。
最后送上一句教训:
删容器不是万能的,清数据卷才是真正的重置。