容器里的 127.0.0.1 不是宿主
容器内的 127.0.0.1 指向容器自己,访问宿主机上的服务需要用宿主在容器网络里的网关地址。Linux 上通行的做法是用 --add-host 把这个名字显式映射为 host-gateway,从 Docker 20.10 起可用。另一个同样重要的前提是:宿主上的服务监听地址必须覆盖容器来源网段,只绑定 127.0.0.1 的宿主服务,容器即使解析对了地址也连不上。
基本信息
| 语义 | 容器内的 127.0.0.1 是容器自身 |
|---|---|
| 写法 | --add-host=host.docker.internal:host-gateway |
| 版本要求 | host-gateway 需要较新的 Docker 版本 |
| 前置条件 | 宿主服务监听地址要覆盖容器来源 |
典型使用场景
- 本地开发:容器里的应用连宿主上跑的数据库或 mock 服务
- 灰度验证:把容器流量临时指向宿主上的新版本服务
- 代理出口:容器通过宿主上的代理访问外网
- 调试对比:宿主与容器分别访问同一服务,对照结果差异
- 迁移过渡:服务从宿主搬到容器期间需要双向访问
配置与验证
配置与验证
# 确认名字解析到宿主网关地址
docker run --rm --add-host=host.docker.internal:host-gateway alpine getent hosts host.docker.internal
# 直连宿主上的服务验证连通性
docker run --rm --add-host=host.docker.internal:host-gateway curlimages/curl:8.8.0 -sS http://host.docker.internal:9000/health
# 宿主侧查看服务监听地址,确认不是只绑回环
ss -ltnp | grep 9000容器内的访问路径
| 访问目标 | 写法 | 说明 |
|---|---|---|
| 容器自身的服务 | 127.0.0.1 | 只在容器网络命名空间内有效 |
| 宿主上的服务 | host.docker.internal | 需显式映射到 host-gateway |
| 同网络的其他容器 | 容器名或别名 | 由内嵌 DNS 解析 |
| 外部服务 | 正常域名 | 依赖配置的上游 DNS |
宿主服务只监听 127.0.0.1 时容器无法直连,需要改为监听容器可达的地址,并配合来源限制控制暴露范围。
把宿主服务放宽到全部地址之前,先确认访问控制:同一容器网络中的其他节点也可能访问到它。
排查这条链路时按顺序走三步:容器内先确认名字解析出的地址是不是网关地址,再测网关地址上的目标端口是否可连,最后回到宿主确认服务监听范围与包过滤规则,逐层排除比反复重建容器有效。