Docker Swarm容器间随机出现Connection refused连接拒绝问题求助
我之前在Docker Swarm集群里碰到过几乎一模一样的偶发连接拒绝问题!咱们一步步拆解可能的原因和解决办法:
Swarm模式下,depends_on 仅仅控制服务的启动顺序,完全不会等待依赖服务完全就绪。如果你的 app_origin 在 app_target 还没完成初始化(比如Spring Boot应用还在加载配置、连接数据库)就发起请求,必然会出现连接拒绝。
解决办法:
给 app_target 添加健康检查,让Swarm确认服务真正就绪后再允许流量访问:
# 在app_target的docker-compose配置里添加 app_target: image: app_target:xxx deploy: resources: limits: memory: ... # 你的现有配置 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] # 替换成你的应用健康检查接口 interval: 5s timeout: 3s retries: 5 start_period: 30s # 根据应用实际启动时间调整,比如大型应用设60s
同时,在 app_origin 的部署配置里添加健康依赖(需要docker-compose 3.9+版本):
app_origin: image: app_origin:2.0.1 deploy: resources: limits: memory: ... depends_on: app_target: condition: service_healthy
如果你的docker-compose版本较低,那就在 app_origin 的代码里加重试逻辑——比如用Apache HttpClient的重试拦截器,或者Spring Retry组件,对付偶发的启动阶段连接失败非常有效。
Swarm的内置DNS服务偶尔会出现缓存延迟,导致 app_origin 拿到的 app_target IP已经失效(比如容器重启后IP变更,但DNS缓存还没更新),这时候请求旧IP就会被拒绝。
排查与解决:
- 出现问题时,进入
app_origin容器执行nslookup app_name,对比返回的IP和app_target当前的实际IP(docker inspect app_target容器ID | grep IPAddress)。 - 解决:
- 检查
app_target的部署配置,如果用了endpoint_mode: dnsrr,改成默认的vip模式——VIP模式下Swarm会维护一个稳定的虚拟IP,避免容器IP变更带来的问题。 - 在应用的HTTP客户端里添加连接超时和重试逻辑,哪怕DNS偶尔抽风也能自动恢复。
- 检查
从你给出的配置看,app_origin 有内存限制,如果 app_target 也设置了严格的资源限制,当内存占用触顶时,容器会被Linux的OOM Killer强制杀死重启,重启过程中就会出现连接拒绝。
排查与解决:
- 查看
app_target的服务日志:docker service logs app_target,搜索关键词OOM或者killed,确认是不是内存不足导致重启。 - 解决:
- 调整资源限制,适当调高
memory的limits值,或者添加reservations保证容器有最低内存可用:app_target: deploy: resources: limits: memory: 1G # 比如从512M调到1G reservations: memory: 512M - 配置合理的重启策略,让容器崩溃后快速恢复:
app_target: deploy: restart_policy: condition: on-failure delay: 5s max_attempts: 3 window: 120s
- 调整资源限制,适当调高
虽然容器在同一Swarm网络,但宿主机的iptables规则、Swarm的overlay网络策略偶尔会出现异常,拦截了容器间的流量。
排查与解决:
- 在出现问题时,登录
app_target所在的宿主机,执行iptables -L -n,检查有没有针对10.0.0.3:8080的DROP规则。 - 检查Swarm网络配置:
docker network inspect <你的overlay网络名>,确认网络是attachable: true,且所有服务都加入了这个网络。 - 解决:如果手动修改过iptables规则,恢复Swarm默认的iptables配置;如果是自定义网络,确保没有设置过于严格的隔离策略。
内容的提问来源于stack exchange,提问作者apenlor

