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

最后送上一句教训

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

相关推荐
天籁晴空7 小时前
Docker Compose 部署完整指南 -- RuoYi-Vue
docker·ruoyi
@土豆7 小时前
Elasticsearch 9.0.1 集群部署(Docker Compose + k8s 部署方式)
大数据·elasticsearch·docker
蛐蛐蛐12 小时前
在Windows 11上安装Docker的踩坑记录
运维·docker·容器
古典和浪漫12 小时前
docker file 中设置软链接和在k8s 中配置同步时区 有什么区别,各自优缺点
docker·容器·kubernetes
尘世壹俗人13 小时前
知识点12---k8s进阶操作方式yaml资源文件
docker·容器·kubernetes
牛奶咖啡1314 小时前
Docker容器实践——Docker常用基础镜像的解析与选择
docker·容器·docker基础镜像·docker基础镜像选择·docker基础镜像最佳实践·docker基础镜像的分类·docker基础镜像的对比
java_logo14 小时前
Docker 部署 Open WebUI + Ollama 完整教程(Windows / Linux 通用)—— 打造自己的本地OpenAI
linux·docker·容器·ollama·open-webui·open-webui部署·open-webui教程
杨浦老苏15 小时前
AI使用追踪和代理网关GoModel
人工智能·docker·ai·api·群晖
程序员老邢15 小时前
【技术底稿 23】Ollama + Docker + Ubuntu 部署踩坑实录:网络通了,参数还在调
java·经验分享·后端·ubuntu·docker·容器·milvus