从容器内连接宿主机服务:几种方式详解与排错
容器访问宿主机服务的三种方式:host.docker.internal 域名、docker0 网桥 IP(Linux)、host 网络模式;连接不通时按监听地址、防火墙、DNS 解析三步排查。
速查:Mac/Windows 容器内用 host.docker.internal:端口;Linux 可加 --add-host host.docker.internal:host-gateway 复用同写法,或直接访问 docker0 网桥 IP(通常 172.17.0.1);Linux 上还可用 --network host 让容器共享宿主机网络栈,localhost 即宿主机。连不通时按"服务监听地址 → 防火墙 → DNS/路由"顺序排查。
方式一:host.docker.internal(跨平台统一写法)
# 容器内
curl http://host.docker.internal:8080
Docker Desktop(Mac/Windows)内置解析。Linux(Docker 20.10+)需显式加映射:
docker run --add-host host.docker.internal:host-gateway myapp
方式二:docker0 网桥 IP(Linux 原生)
ip addr show docker0 | grep 'inet ' # 查得,如 172.17.0.1
容器内直接访问 http://172.17.0.1:8080。不依赖额外参数,但 IP 可能随 Docker 网络配置变化。
方式三:host 网络模式(Linux)
docker run --network host myapp
容器与宿主机共用网络栈,localhost:8080 直通宿主机服务。代价:无网络隔离、端口直接冲突、Mac/Windows 不适用。
连不通?三步排查
- 服务监听地址:宿主机上
ss -ltnp | grep 8080,必须是0.0.0.0:8080或宿主机内网 IP;127.0.0.1:8080对网桥来的流量不响应。 - 防火墙:
iptables -L -n/firewall-cmd --list-all,确认 docker0 网段入站放行。 - 域名解析:容器内
getent hosts host.docker.internal,解析不到说明没加--add-host。
观测云对照
跨边界的调用要纳入链路。 容器应用访问宿主机上的数据库/缓存,这段跨度用观测云 APM 串成完整调用链;两侧日志统一采集到日志查看器,定界"是网络不通还是服务报错"只需一次查询。
常见问题(FAQ)
Q:docker-compose 里怎么写?
A:extra_hosts: ["host.docker.internal:host-gateway"],然后服务内统一用该域名。
Q:能访问宿主机的 unix socket 吗?
A:可以挂载进来(如 -v /var/run/mysqld.sock:/sock/mysqld.sock),比走 TCP 更直接,但仅限同机。
Q:Swarm/K8s 环境下呢?
A:K8s 里用节点 IP + hostPort 或 hostNetwork;长期方案是把依赖服务也纳入编排统一管理。