自定义bridge网络通过内置DNS支持容器名解析,使同网容器可直接通过服务名通信;默认docker0桥接网络不支持该功能,且容器间通信无需端口映射,关键在于服务监听地址须设为0.0.0.0而非127.0.0.1。

不需要映射主机端口,只要容器在同一个自定义 Docker 网络(如 bridge)中,就能直接通过容器名和内部端口通信。
为什么不用映射主机端口也能互通
默认的 docker run 使用的是 bridge 网络,但 Docker Desktop 的默认桥接网络(docker0)不支持容器名解析。真正能靠名字互通的,是用户自己创建的自定义 bridge 网络——Docker 会自动为该网络中的容器启动一个内建 DNS,让 curl http://backend:3000 这类调用生效。
- 容器名就是 DNS 名,无需额外配置(前提是同网络)
- 通信走的是 Docker 内部虚拟网桥,不经过宿主机 iptables 或端口映射规则
- 映射主机端口(
-p 8080:3000)只对「从宿主机或外部访问容器」有意义,对容器间调用是冗余且可能引入端口冲突的
如何确保容器能用名字互相访问
关键不是改启动参数,而是先建网、再连网:
- 运行
docker network create mynet创建自定义网络 - 启动容器时显式指定网络:
docker run --network mynet --name backend -d my-backend-image - 另一个容器也进同一网络:
docker run --network mynet --name frontend -d my-frontend-image - 在
frontend容器里执行curl http://backend:3000/health就能通
注意:不要依赖默认的 bridge 网络做服务发现;也不要给容器加 --network host,否则 localhost 在不同容器里指向不一致,反而容易出错。
常见错误:明明在同一个网络,curl 却超时或拒绝连接
这不是网络问题,而是服务监听地址写死了 127.0.0.1 或 localhost:
- Node.js 应用若用
app.listen(3000, '127.0.0.1'),只会监听本地回环,其他容器连不上 - 必须改成
app.listen(3000, '0.0.0.0')或省略 host 参数(默认即0.0.0.0) - Python Flask 同理:
app.run(host='0.0.0.0'),不能是'localhost' - 可进容器执行
ss -tlnp | grep :3000确认监听的是*:3000而非127.0.0.1:3000
host.docker.internal 是给容器访问宿主机用的,不是容器间通信方案
这个 DNS 名是 Docker Desktop 提供的便利机制,专用于让容器安全访问宿主机上的服务(比如宿主机跑的数据库、Redis)。它不参与容器间的服务发现:
-
host.docker.internal解析为宿主机在 Docker 虚拟网桥上的 IP(通常是192.168.65.2) - 如果你在容器 A 里
curl http://host.docker.internal:8080,实际访问的是宿主机的 8080 端口,不是容器 B - 跨容器调用永远优先走自定义网络 + 容器名,而不是绕道宿主机再转发
最易被忽略的一点:监听地址写成 127.0.0.1 比网络配置错误更隐蔽,也更常导致“网络通但服务连不上”的假象。











