Docker容器跨服务器连接PostgreSQL数据库超时问题求助
看起来你遇到的是Docker容器无法跨服务器连接PostgreSQL的网络问题,我来帮你梳理排查方向和解决方案:
核心问题分析
宿主机(192.168.1.30)能正常通过公网IP连接PostgreSQL,但容器内却超时,大概率是网络路由或防火墙规则导致的,尤其是你用公网IP连接时可能触发了NAT回环问题(很多环境下不支持容器访问宿主机的公网IP)。
分步排查与解决建议
1. 优先改用PostgreSQL的内网IP连接
放弃用公网IP 185.253.74.227,直接用PostgreSQL服务器的内网IP 192.168.1.118 作为连接地址。这样既避免了公网NAT的问题,也更高效。
- 修改你的连接字符串为:
"Server=192.168.1.118;Port=5432;Database=forex_crm;User Id=ampiex;Password=my_password;Trust Server Certificate=true;" - 然后在容器内测试连通性:
docker exec -it crm_api bash psql -h 192.168.1.118 -U ampiex -d forex_crm -p 5432
2. 验证容器到内网IP的基础连通性
如果用内网IP还是连不上,先确认容器能不能访问到PostgreSQL服务器:
- 在容器内ping内网IP:
ping 192.168.1.118 - 用nc测试端口是否开放:
nc -zv 192.168.1.118 5432
如果ping不通,说明容器到内网的路由有问题;如果ping通但端口连不上,重点看防火墙规则。
3. 检查PostgreSQL服务器的UFW规则顺序
UFW规则是按顺序匹配的,前面的拒绝规则会覆盖后面的允许规则。你虽然加了允许172.22.0.3(容器IP)的规则,但可能被前面的规则挡住了:
- 查看UFW规则的完整顺序:
sudo ufw status numbered - 如果允许容器IP的规则排在后面,调整顺序(比如把它移到第1位):
sudo ufw insert 1 allow from 172.22.0.3 to any port 5432 - 也可以临时关闭UFW测试:
sudo ufw disable
如果关闭后能连接,说明就是UFW规则的问题,重新整理规则即可。
4. 开启宿主机的IP转发功能
Docker容器要访问内网其他服务器,需要宿主机开启IP转发:
- 检查当前状态:
sysctl net.ipv4.ip_forward - 如果输出是
net.ipv4.ip_forward = 0,临时开启:sudo sysctl -w net.ipv4.ip_forward=1 - 持久化设置(重启后生效):
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
5. 修正你的docker-compose配置
你之前的docker-compose里错误地定义了postgres服务,但实际PostgreSQL在另一台服务器,所以这个配置没用。正确的配置应该直接指向内网IP:
version: '3.8' services: crm_api: image: ampitexcrmapi:latest ports: - "8080:80" environment: DATABASE_CONNECTION_STRING: "Server=192.168.1.118;Port=5432;Ssl Mode=Require;Database=forex_crm;User Id=ampiex;Password=my_password;Trust Server Certificate=true;" crm_front: image: crm_front:latest ports: - "3002:3002"
6. 查看PostgreSQL日志定位问题
如果以上步骤都没解决,去PostgreSQL服务器查看日志,看有没有连接请求的记录:
tail -f /var/log/postgresql/postgresql-12-main.log
- 如果看不到容器的连接尝试,说明请求根本没到PostgreSQL,重点排查网络路由;
- 如果看到拒绝信息,再调整
pg_hba.conf(不过你的pg_hba已经允许0.0.0.0/0,大概率不是这个问题)。
总结
最可能的原因是用公网IP连接触发NAT回环,或者UFW规则顺序不对,先尝试改用内网IP连接,再逐步排查网络和防火墙问题。
备注:内容来源于stack exchange,提问作者malboro_way

