[Docker] 无需网络共享,通过主机端口实现容器间通信 (host.docker.internal)
标签: Docker, DevOps, 网络, host.docker.internal
1. 问题情况
在开发环境中,通常要用 Docker 来管理多个服务。
-
App-A(例如: DRF) 在network-A中。 -
App-B(例如: Nextcloud) 在network-B中。 -
两个容器在同一主机上运行。
-
App-B绑定在主机的8080端口上。 (例如:docker run -p 8080:80 ...)
需要在 App-A 中调用 App-B 的 API。 我不想麻烦地将两个网络连接在一起。 我可以直接调用主机的 8080 端口吗?
如果在容器内部调用 localhost:8080 或 127.0.0.1:8080,那么这指向的是容器自身而不是主机。
2. 解决方案: host.docker.internal
最简单的解决方案是使用名为 host.docker.internal 的特殊 DNS 名称。
host.docker.internal: 在容器内部被解析为主机 IP 地址的特殊主机名。
在 App-A (DRF) 的代码中调用 Nextcloud 时,URL 如下设置。
# DRF (App-A) 内部代码
import requests
# 使用 'host.docker.internal' 替代 'localhost'。
NEXTCLOUD_URL = "http://host.docker.internal:8080"
try:
response = requests.get(NEXTCLOUD_URL)
print(f"Nextcloud 连接成功: {response.status_code}")
except requests.exceptions.ConnectionError:
print("Nextcloud 连接失败")
在容器内部使用 curl 测试时也是同样的情况。
# 在 App-A 容器内部执行
curl http://host.docker.internal:8080
3. ⚠️ 重要: Linux 主机环境设置
使用 Docker Desktop (macOS, Windows) 的用户,host.docker.internal 默认是有效的。
而在Linux 主机环境中,需要手动添加这个设置。可以使用名为 host-gateway 的特殊关键字来映射主机 IP。
方法 1: 使用 docker run
添加 --add-host 标志。
docker run \
--add-host=host.docker.internal:host-gateway \
--network network-A \
my-drf-app-image
方法 2: 使用 docker-compose.yml
在 App-A (DRF) 服务中添加 extra_hosts。
services:
drf-app:
image: my-drf-app-image
networks:
- network-A
extra_hosts:
# 将 host.docker.internal 映射到主机 IP (host-gateway)
- "host.docker.internal:host-gateway"
# ... (network-A 定义) ...
4. 总结
在不同的 Docker 网络之间通信时,无需复杂连接网络。
-
将目标容器 (Nextcloud) 绑定到主机端口 (
8080)。 -
在调用的容器 (DRF) 中以
http://host.docker.internal:8080地址发起请求。 -
如果主机是Linux,请别忘了在调用的容器中添加
extra_hosts(host.docker.internal:host-gateway) 设置。
目前没有评论。