Docker Compose容器间通信Connection refused失败怎么办?网络配置怎么修?

文章导读
遇到 Docker Compose 容器间通信出现"Connection refused"错误,优先检查服务是否在同一网络、端口是否正确暴露、目标服务是否正常运行,大多数问题通过统一网络配置和清理旧资源就能解决。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 参考来源
A A

遇到 Docker Compose 容器间通信出现"Connection refused"错误,优先检查服务是否在同一网络、端口是否正确暴露、目标服务是否正常运行,大多数问题通过统一网络配置和清理旧资源就能解决。

先说结论:Connection refused 通常不是代码问题,而是容器网络隔离或端口映射配置不当导致的,按网络→端口→服务状态的顺序排查最有效。

  • 先确认:所有需要通信的服务是否定义在同一 networks 配置中
  • 先处理:清理旧容器和网络资源,避免遗留配置干扰
  • 再验证:进入容器内部测试服务名解析和端口连通性

命令速用版

以下是排查时最常用的命令,按顺序执行可快速定位问题:

docker compose ps
docker network inspect <项目名>_default
docker compose exec <服务名> nslookup <目标服务名>
docker compose down && docker compose up -d
docker inspect <容器 ID> | grep -A 20 NetworkSettings

为什么会这样

Docker Compose 默认为每个项目创建独立的桥接网络,服务之间通过内置 DNS 服务器用服务名互相解析。但如果配置不当,会出现以下几种情况:

网络隔离:如果两个服务没有显式加入同一网络,它们处于不同的网络命名空间,无法通过服务名通信。默认情况下 Compose 会创建项目默认网络,但显式定义 networks 配置更可靠。

端口暴露问题:容器内的服务需要监听 0.0.0.0 而非 127.0.0.1,否则其他容器无法访问。ports 配置只影响宿主机访问,容器间通信不需要端口映射,但服务本身必须正确监听。

DNS 解析失败:Docker 的内置 DNS 仅在自定义网络中生效,默认 bridge 网络不支持自动服务名解析。如果服务名拼写错误或网络配置遗漏,会出现"could not resolve host"错误。

服务未就绪:目标服务可能还在启动中,或者启动失败后退出。depends_on 只控制启动顺序,不等待服务就绪,需要配合健康检查或重试机制。

分步处理

第一步:检查服务状态

先确认所有相关容器是否正常运行:

docker compose ps

如果看到某个服务状态是 Exited 或 Restarting,查看其日志:

docker compose logs <服务名>

常见情况是数据库服务启动较慢,应用容器先启动导致连接失败。可以在 docker-compose.yml 中添加健康检查:

services:
  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      retries: 5
  app:
    depends_on:
      db:
        condition: service_healthy

第二步:验证网络配置

检查 docker-compose.yml 中是否显式定义了共享网络:

services:
  web:
    image: nginx
    networks:
      - app-network
  api:
    image: my-api
    networks:
      - app-network
networks:
  app-network:
    driver: bridge

如果缺少 networks 配置,所有服务默认会在项目默认网络中,但显式定义更清晰。查看实际网络中的容器列表:

docker network inspect <项目名>_default

在 Containers 字段中确认所有需要通信的服务都在同一网络里。

第三步:测试容器内连通性

进入源服务容器,测试能否解析和访问目标服务:

docker compose exec <源服务> ping <目标服务名>
docker compose exec <源服务> nslookup <目标服务名>

如果 ping 不通但 nslookup 能解析,可能是目标服务未监听正确地址。进入目标容器检查:

docker compose exec <目标服务> netstat -tulpn

确认服务监听的是 0.0.0.0 而非 127.0.0.1。

Docker Compose容器间通信Connection refused失败怎么办?网络配置怎么修?

第四步:清理并重建

如果上述检查都正常但仍无法通信,可能是旧网络资源干扰。彻底清理后重建:

docker compose down
docker network prune -f
docker compose up -d

down 命令会移除容器和网络,prune 清理未使用的网络资源,避免遗留配置影响新部署。

怎么验证是否生效

完成配置修复后,按以下方式验证:

服务名解析测试:进入任意服务容器,执行 nslookup 目标服务名,应能返回正确的容器 IP 地址。

端口连通性测试:使用 curl 或 telnet 测试目标端口:

docker compose exec <源服务> curl -v http://<目标服务名>:<端口>

如果返回 HTTP 响应或连接成功,说明网络通信正常。

应用日志检查:查看应用日志中是否还有 Connection refused 错误:

docker compose logs <服务名> | grep -i "refused\|error\|fail"

正常情况不应出现连接拒绝类错误。

外部访问测试:如果涉及宿主机访问,验证端口映射:

docker compose port <服务名> <容器端口>

确认映射的宿主机端口,然后用 curl 或浏览器访问测试。

常见坑

links 已废弃:旧教程中常用的 links 关键字在 Compose v3 后不再推荐,应使用 networks 配置实现服务间通信。links 在某些场景下可能不生效。

depends_on 不等于就绪:depends_on 只控制启动顺序,不等待服务完全就绪。数据库类服务需要配合 healthcheck 或使用等待脚本。

服务名与容器名混淆:在 Compose 网络中,服务间通信使用服务名(services 下的键名),而非 container_name。如果指定了 container_name,仍应用服务名访问。

防火墙拦截:宿主机防火墙可能拦截容器间通信,尤其是在云服务器环境中。检查安全组规则是否允许相关端口。

应用监听地址错误:某些应用默认监听 127.0.0.1,在容器内这会导致其他容器无法访问。需要配置应用监听 0.0.0.0。

多网络隔离:如果项目定义了多个网络,服务必须加入需要通信的网络。跨网络通信需要额外配置网络别名或使用外部网络。

参考来源

  • Docker 官方文档 - Docker Compose 网络配置
  • 解决 Docker Compose 容器网络连接问题的 6 个实用技巧 - 网络配置原理与诊断方法
  • Docker 故障码和解决办法 – Error: connection refused - 常见原因与排查步骤
  • Docker Compose 容器间通信与 MongoDB 连接故障排除 - 服务发现与网络机制详解
  • Docker Compose 中 PHP 与 Nginx 网络不通 - 网络模式对比与配置示例