记一次 Docker PostgreSQL 连接认证失败的排查与解决

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 模式修改密码会自动转换为当前认证方法支持的格式

避免再次踩坑的建议

  1. 修改配置统一通过宿主机文件操作

    不要用 docker exec ... echo >> 追加,而是直接编辑 /data/pgvector/pg_hba.conf,然后 docker restart

  2. 保持认证方法为 md5
    psycopg2psql 等绝大多数客户端都良好支持 md5,除非你明确需要 scram-sha-256

  3. 彻底重置数据库(如需)

    bash 复制代码
    docker 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
  4. 检查认证失败的日志

    bash 复制代码
    docker logs my_pgvector | grep -i "password\|authentication"

结语

这个问题本质上是 PostgreSQL 客户端认证配置(HBA)数据卷持久化 共同作用的结果。看似简单的"密码错误",背后却隐藏着配置顺序、认证方式、驱动兼容性、数据卷残留等多个因素。希望通过本文的记录,能帮助你快速定位类似问题,少走弯路。

最后送上一句教训

删容器不是万能的,清数据卷才是真正的重置。

相关推荐
BullSmall6 小时前
第三方软件安全-Dependency‑Track Docker 部署
安全·docker·容器
harmony&7 小时前
Docker 容器技术从入门到实战:容器、网络、存储与监控全解析
docker·云原生
IT大白鼠10 小时前
Docker 私有仓库管理:Harbor 企业级仓库搭建与镜像全生命周期管理
运维·docker·容器
bgy666613 小时前
从零上手 Docker,容器技术完整入门指南
运维·docker·容器
pride.li17 小时前
Docker教程-Docker安装与镜像配置
运维·docker·容器
bgy666617 小时前
Docker Swarm 容器编排实战指南
运维·docker·容器
力江19 小时前
GitLab 私有化部署实战 —— 从 Omnibus 到 Docker 的踩坑之旅
docker·容器·gitlab
深念Y20 小时前
Docker 镜像体积从 110MB 降到 13MB 后端服务的瘦身
运维·docker·容器
虎王物联20 小时前
Docker容器安全加固:securityContext与seccomp在IoT边缘节点的隔离实践
物联网·安全·docker
YIAN20 小时前
从 Docker 容器操作到 TS 高级类型:前端开发者必备的两套核心工具全解
后端·docker