先看双方接在哪张网
两个容器互相访问失败,最常见的原因不是防火墙,而是它们根本不在同一张网络上,或者所在的网络不支持按名字解析——默认 bridge 网络就没有内嵌 DNS,用容器名去连必然失败,只有用户自定义网络才提供按容器名与别名的解析。排查第一步是把双方各自的网络归属查清楚,其次再看端口是否监听、是否只绑在本地地址上。
基本信息
| 第一步 | docker inspect 看 NetworkSettings.Networks 字段 |
|---|---|
| 解析规则 | 只有用户自定义网络支持按容器名与别名解析 |
| 临时验证 | docker network connect 把一方加入另一方的网络 |
| 其它因素 | internal 网络无外网出口,容器间通信也可被守护进程关闭 |
典型使用场景
- 应用连不上数据库:两个容器分属不同网络,名字解析不到
- 默认 bridge 上按名互访失败:该网络没有内嵌 DNS,需要换自定义网络
- 同网络也不通:服务监听在 127.0.0.1,其他容器无法接入
- 跨项目调用:不同 compose 项目的网络互相隔离,需要显式共享网络
- 排障后固化:把验证有效的网络归属写进编排文件,避免手工 connect 的临时改动丢失
排查步骤
排查步骤
# 看双方各自接了哪些网络
docker inspect -f '{{json .NetworkSettings.Networks}}' app
docker inspect -f '{{json .NetworkSettings.Networks}}' db
# 在网络内验证名字解析,getent 比 nslookup 更贴近应用行为
docker exec app getent hosts db || echo 'resolve-fail'
# 临时把一方加入另一方的网络做验证
docker network connect app-net db
# 确认服务监听地址,绑定 127.0.0.1 的端口无法被其他容器访问
docker exec db sh -c 'ss -ltnp 2>/dev/null || netstat -ltnp'现象与原因对照
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 按容器名连不上 | 不在同一张自定义网络 | 加入同一网络后重试 |
| IP 能通、名字不通 | 在默认 bridge 网络上 | 改用用户自定义网络 |
| 同网内仍连不上 | 服务只监听 127.0.0.1 | 改为监听全部地址并配合访问控制 |
| 与外部完全隔绝 | 网络被设为 internal | 核对创建参数,需要外联时另接一张网络 |
生产环境让相关服务共用一张自定义网络,默认 bridge 适合临时调试;容器名解析只在自定义网络内建,写死 IP 的做法在多副本场景下更脆。
跨 compose 项目访问要显式共享网络:一个项目用 external 引用另一个项目创建的网络,比手工 connect 更可维护。