如何从 Docker 容器内部访问宿主机上的端口?
容器内访问宿主机服务,用特殊域名 host.docker.internal:端口(Linux 需 --add-host host.docker.internal:host-gateway),或宿主机内网 IP;宿主机服务要监听 0.0.0.0 而非仅 127.0.0.1。
做法:容器内把 localhost 换成宿主机的地址——Mac/Windows 直接用 host.docker.internal:端口;Linux 启动时加 --add-host host.docker.internal:host-gateway 后用同样域名,或直接用宿主机的内网 IP。前提是宿主上的服务监听 0.0.0.0(或宿主机内网 IP),只监听 127.0.0.1 是访问不到的。
典型场景
宿主机上跑着 MySQL(3306),容器里的应用要连它:
# 容器内测试连通性
curl http://host.docker.internal:3306 # Mac/Windows 直接可用
# Linux 启动容器时先加映射
docker run -d --add-host host.docker.internal:host-gateway myapp
docker-compose:
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
用宿主机 IP 的备选方案
查宿主机在 docker 网桥上的地址:
ip addr show docker0 | grep inet # 通常是 172.17.0.1
容器内访问 http://172.17.0.1:3306。缺点:网桥 IP 可能随 Docker 配置变化,不如 host-gateway 稳定。
三个常见失败原因
- 服务只听 127.0.0.1:容器流量从网桥进来,不算本地回环,必须让服务监听
0.0.0.0或宿主机内网 IP(注意评估暴露面,配合防火墙只放行内网)。 - 防火墙拦截:宿主机 iptables/firewalld 拦了 docker0 网段的入站。
- 容器内还在用 localhost:容器内 localhost 是容器自己,不是宿主机。
反向问题:宿主机访问容器
方向反过来时用端口映射 docker run -p 8080:80,宿主机访问 localhost:8080——两个方向机制不同,别混淆。
观测云对照
混合部署的链路要一起看得见。 容器化应用连宿主机数据库是过渡期常见架构,观测云 APM 能把这段调用链完整呈现,DataKit 同时采集容器日志与宿主机数据库日志,跨边界问题一处排查。
常见问题(FAQ)
Q:K8s 里 Pod 怎么访问节点上的服务?
A:用节点 IP(status.hostIP 可注入环境变量)或 hostNetwork;推荐把服务也容器化或用 Service 抽象。
Q:host.docker.internal 能 ping 通但连不上端口?
A:DNS 解析正常但服务监听地址不对或防火墙拦了,按上面三点逐个查。
Q:生产环境推荐这种做法吗?
A:权宜之计可以,长期建议服务全部容器化编排,或数据库用云服务的内网地址,减少宿主机耦合。