容器能用 localhost 访问但宿主机 IP 不行,根本原因是 WSL2 默认仅绑定 127.0.0.1、Docker Desktop 自动加 127.0.0.1 前缀、Windows 防火墙拦截及 host 模式在 Windows 失效;需改 WSL2 网络模式、显式用 0.0.0.0 绑定、配置防火墙规则,并避免使用 host 模式。

容器能用 localhost 访问,但宿主机 IP 不行?先确认是不是 WSL2 网络模式问题
这是 Docker Desktop + WSL2 在 Windows 上的典型表现:浏览器访问 http://localhost:8080 成功,换成 http://192.168.1.100:8080(你的宿主机真实 IP)就失败。根本原因不是端口没映射,而是 WSL2 虚拟机默认只把端口绑定到 127.0.0.1,不监听宿主机网卡。
检查方式很简单:
netstat -ano | findstr :8080
如果输出里只有 127.0.0.1:8080 或 [::1]:8080,没有 0.0.0.0:8080,那就坐实了——Docker Desktop 没放开对外监听。
解决办法是改 WSL2 的网络配置:
- 打开 Windows 设置 → 搜索 “WSL” → 进入 WSL Settings
- 找到 Networking mode,确保设为 Default(不是 “Isolated”)
- 打开 Host address loopback 开关(该选项在 2025 年后版本中默认关闭,必须手动开启)
- 重启 WSL2:
wsl --shutdown,再重新启动 Docker Desktop
docker run -p 映射时,端口绑定地址被悄悄限制了
Docker Desktop 的 -p 默认行为和 Linux 原生 Docker 不同:它会自动加一个 127.0.0.1: 前缀,变成 -p 127.0.0.1:8080:80,这导致只响应本地回环,不响应局域网请求。
要强制暴露到所有接口,必须显式写全:
docker run -d -p 0.0.0.0:8080:80 nginx
注意三点:
-
0.0.0.0是关键,不能省略或写成空 - 别用
-p 8080:80简写,Docker Desktop 会帮你“优化”掉绑定地址 - 如果用 Compose,得写成
"0.0.0.0:8080:80"字符串形式,YAML 里数字开头会被解析成整数,丢掉前缀
Windows 防火墙可能拦住了非 localhost 的入站连接
即使端口绑定了 0.0.0.0,Windows 防火墙仍可能放行 127.0.0.1 流量,却拦截来自本机其他 IP(比如 192.168.1.100)的请求——因为 Windows 把“本机不同 IP 间通信”也当作网络流量处理。
快速验证方法:
- 临时关闭防火墙测试:
netsh advfirewall set allprofiles state off - 如果此时宿主机 IP 能访问了,说明就是它拦的
- 恢复防火墙后,添加入站规则:
netsh advfirewall firewall add rule name="Docker Port 8080" dir=in action=allow protocol=TCP localport=8080
注意:别只加 127.0.0.1 白名单,防火墙规则是按协议+端口生效的,IP 绑定由 Docker 控制,防火墙只管“是否允许这个端口进来”。
别踩 network_mode: "host" 这个坑
看到“宿主机 IP 不行”,有人会想:干脆用 host 模式绕过网络栈?在 Windows 上这招完全失效。
因为 Docker Desktop 的 host 模式实际绑定的是 WSL2 虚拟机的 localhost,不是 Windows 宿主机的。你容器里 curl http://localhost:3306 访问的是 WSL2 里的服务,不是 Windows 上跑的 MySQL。
所以:
- Windows 下不要用
network_mode: "host"解决“宿主机 IP 访问”问题 - 它对容器访问宿主机服务无效,反而让
-p映射彻底失效(docker port查不到端口) - 真正需要容器访问宿主机服务时,用
host.docker.internal或--add-host=host.docker.internal:host-gateway
最易忽略的一点:WSL2 的 host.docker.internal 解析依赖于 DNS 服务,如果你在 WSL2 里手动改过 /etc/resolv.conf 或禁用了 systemd-resolved,这个域名也会失效——此时只能退回到硬编码 172.17.0.1(Linux bridge 网关)或查 WSL2 的实际网关 IP。











