记一次 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)数据卷持久化 共同作用的结果。看似简单的"密码错误",背后却隐藏着配置顺序、认证方式、驱动兼容性、数据卷残留等多个因素。希望通过本文的记录,能帮助你快速定位类似问题,少走弯路。

最后送上一句教训

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

相关推荐
小森林之主8 小时前
Docker Compose 紧急救援:凌晨3点服务器报警的解决方案
docker·微服务·容器化·docker compose·故障排除
杨了个杨898211 小时前
Docker Compose 简介及应用
运维·docker·容器
豆瓣鸡11 小时前
XXL-JOB 定时任务——从 Docker 部署到分片广播,分布式任务调度落地
spring boot·分布式·docker·定时任务
Re_Virtual12 小时前
基于web的轻量级http测试工具——Restfox
http·docker·开源·restfox
java_logo15 小时前
Docker 部署 Home Assistant:在群晖 NAS 或 Linux 上打造家庭智能中枢
linux·docker·容器·homeassistant·轩辕镜像·homeassistant部署·homeassistant教程
极客先躯16 小时前
高级java每日一道面试题-2026年04月18日-实战篇[Docker]-如何处理金融行业的时序数据容器化?
java·运维·docker·容器·金融·时序数据·高级面试
杨了个杨898218 小时前
docker的网络模式
网络·docker·容器
jackletter19 小时前
docker上常用的软件安装
运维·docker·容器
Zhu75819 小时前
对docker环境的postgresql数据库做快速初始化
数据库·docker·postgresql