什么是“host.docker.internal”的linux等价物

Posted

技术标签:

【中文标题】什么是“host.docker.internal”的linux等价物【英文标题】:What is linux equivalent of "host.docker.internal" [duplicate] 【发布时间】:2018-07-10 19:07:20 【问题描述】:

在 Mac 和 Windows 上,可以在容器内使用 docker.for.mac.host.internal(替换 docker.for.mac.localhost)和 docker.for.win.host.internal(替换 docker.for.win.localhost host.docker.internal(Docker 18.03+)。

有没有一种适用于 Linux 的工具,无需传递环境变量或使用各种 CLI 命令提取它即可开箱即用?

【问题讨论】:

在 18.03 中有一个 docker.host.internal,但它对我不起作用。 From inside of a Docker container, how do I connect to the localhost of the machine?的可能重复 有一个开放的PR 将“host.docker.internal”功能添加到Linux。等到它被接受,现在作为一种解决方法,您可以使用 special container 添加统一的“dockerhost”主机,您可以从 docker 使用它。 需要注意的是,docker-for-windows是一个特定的产品线,一般不会涵盖windows上的docker。例如,我在 Windows 上使用 docker,使用 docker-toolbox (OG),这样它与我的其余设置的冲突较少,我不需要 HyperV。在这个线程中有一个使用 grep、awk 和 netstat 的答案,这对我有用;虽然一般来说,混合网络环境也可以使用 LAN 或 WAN 级别的主机名来解决,而不是机器主机名。这比在 docker VM 上进行黑客攻击更明确、更灵活/可组合 【参考方案1】:

取决于你想要做什么。如果您使用--net=host 运行,localhost 应该可以正常工作。如果您使用默认网络,请使用静态 IP 172.17.0.1。我怀疑两者的行为都不会与那些域完全相同。

【讨论】:

哇! 172.17.0.1 确实有效!我在文档或任何抱怨host.docker.internal 不起作用的论坛中都找不到这个。是否保证此 IP 始终链接到主机? 您可以编辑您的 /etc/hosts 并添加 172.17.0.1 docker.host.internal 我可以证明 172.17.0.1-trick 这适用于 GitHub Actions! @JulesColle 只要您在默认网络上,它就是“保证”。 172.17.0.1 不是魔术,只是网络bridge 的网关,恰好是主机。除非另有说明,否则所有容器都将连接到 bridge。 See here 这不适用于所有情况。如果您有其他网络,将创建一个新接口:172.17.0.1、172.18.0.1、172.19.0.1 等等(尝试ifconfig 列出所有接口)。您必须手动获取网络的 IP。【参考方案2】:

对于 linux 系统,您可以 - 从 docker 引擎的主要版本 20.04 开始 - 现在还可以通过 host.docker.internal 与主机通信。这不会自动运行,但您需要提供以下运行标志:

--add-host=host.docker.internal:host-gateway

在此处查看答案:https://***.com/a/61424570/3757139

另请参阅下面的此答案以添加到 docker-compose 文件 - https://***.com/a/67158212/243392

【讨论】:

有没有办法在 daemon.json 中启用它?我正在考虑 Rancher 和 Kubernetes 的测试环境,我不想在其中处理众多容器中的每一个。 在 CentOS 上运行--add-host=host.docker.internal:host-gateway 时收到错误invalid argument "host.docker.internal:host-gateway" for "--add-host" flag: invalid IP address in add-host: "host-gateway" 您是否需要将host-gateway 替换为实际主机IP? 神奇的 IP 号码起作用了:`--add-host=host.docker.internal:172.17.0.1 ` 这也适用于我。在我的例子中,172.17.0.1 是桥接网络的网关地址。如果有人有不同的网络设置,他们可以通过 docker inspect 来获得。 只有较新的 docker 版本有神奇的字符串 host-gateway,它转换为 docker 默认的网桥网络 ip(或使用 docker 桌面时主机的虚拟 IP)。你可以测试运行:docker run --rm --add-host=host.docker.internal:host-gateway ubuntu:18.04 cat /etc/hosts,然后看看它是否有效并在hosts文件中显示ip(里面应该有172.17.0.1 host.docker.internal这样的行)。【参考方案3】:

如果您使用的是Docker Compose + Linux,则必须手动添加它(至少现在是这样)。在您的 docker-compose.yaml 文件上使用 extra_hosts

version: '3.7'

services:

  fpm:
    build:
      context: .
    extra_hosts:
      - "host.docker.internal:host-gateway"

文档 - https://docs.docker.com/compose/compose-file/compose-file-v3/#extra_hosts

不要忘记更新 Docker,因为这只适用于 Docker v20.10+

来源:https://github.com/docker/for-linux/issues/264#issuecomment-784985736

【讨论】:

太棒了!最后我也可以在 linux 上使用 xdebug 了 :-) @funder7 大声笑,是的,我这样做是为了使用 xdebug :) 如果我想访问主机上的 3000 端口,这是我从容器中访问它的方式:http://host.docker.internal:3000/ 吗? 这样做添加的主机条目似乎在错误的子网中【参考方案4】:

一种解决方案是使用特殊容器将流量重定向到主机。你可以在这里找到这样的容器:https://github.com/qoomon/docker-host。这个想法是从容器中获取默认路由并将其安装为传入连接的 NAT 网关。

一个虚构的示例用法:

docker-host:
  image: qoomon/docker-host
  cap_add: [ 'NET_ADMIN', 'NET_RAW' ]
  restart: on-failure
  environment:
    - PORTS=999

some-service:
  image: ...
  environment:
    SERVER_URL: "http://docker-host:999"
  command: ...
  depends_on:
    - docker-host

【讨论】:

【参考方案5】:

这是我的解决方案:

IP_ADDRESS=$(ip addr show | grep "\binet\b.*\bdocker0\b" | awk 'print $2' | cut -d '/' -f 1)

然后在 docker-compose 中:

extra_hosts:
  docker.host: $IP_ADDRESS

【讨论】:

在我的 Ubuntu VM 上,这是 172.17.0.1,与上述答案相符。 在 Linux/Debian docker 上使用这个 cmd 我什么也得不到。更好的是:/sbin/ip route|awk '/default/ print $3 ' 上述ip route 示例打印网关,而不是docker0 io。以下应该可以工作:# ip route | awk '/docker0/ print $9'【参考方案6】:

对于 linux,主机没有默认的 DNS 名称。这可以通过运行命令来验证:

docker run -it alpine cat /etc/hosts

已请求此功能,但未实现。您可以查看此issue。如前所述,您可以使用以下命令从容器中查找主机的 IP。

netstat -nr | grep '^0\.0\.0\.0' | awk 'print $2'

或者,您可以通过docker run --add-host dockerHost:<ip-address> ... 将主机 ip 提供给运行命令

【讨论】:

这绝不是等价的。拥有可以用 dns 解决的东西让您能够将其放入配置文件中,而无需评估或 sed'ing 或其他时髦的东西。 grep | awk 往往只是 awk:awk '/^0\.0\.0\.0/print $2' :) 好吧,我想说声谢谢。这适用于我使用 docker-machine 的 Windows 设置(我知道 OG)。通常我会运行一个直通 nginx,这样我就可以通过单个容器与 docker 对话,但与主机对话似乎是非常特定于操作系统/设置的。它对我有用,我为此欣喜若狂。谢谢!【参考方案7】:

https://github.com/docker/for-linux/issues/264

IP=$(ip -4 route list match 0/0 | awk 'print $3')
echo "Host ip is $IP"
echo "$IP   host.docker.internal" | sudo tee -a /etc/hosts

它会将host.docker.internal 添加到您的主机。然后就可以在 xdebug config 中使用了。

这是docker-compose.yml中的环境变量示例

XDEBUG_CONFIG: remote_host=host.docker.internal remote_autostart=On remote_enable=On idekey=XDEBUG remote_log=/tmp/xdebug.log remote_port=9999

【讨论】:

【参考方案8】:

使用 docker0 接口 ip,比如 172.17.0.1,可能是一个很好的解决方法。

只需确保您需要访问的服务侦听外部连接即可。一个典型的例子是默认绑定到 127.0.0.1 的 mysql,导致无法访问,直到您允许外部连接(例如绑定到 0.0.0.0)

【讨论】:

【参考方案9】:

host.docker.internal 仅存在于 Windows WSL 中,因为 Docker Desktop for Windows 在特殊的 WSL VM Docker-Desktop 中运行 Docker 守护程序。它有自己的 localhost 和自己的 WSL2 接口来与 Windows 通信。此 VM 没有静态 IP。每次创建 VM 时都会生成 IP,并通过生成的 /etc/hosts 中的 host.docker.internal 将其传递给每个发行版。尽管没有网桥或真正的 v-switch,但在 VM 内部网络的 eth0 上打开的所有端口都映射到主机本地网络,但不在主机的 ETH0 上。 没有真正的网桥和端口映射 - 无需配置。 在 WSL VM 内部,它的 localhost 与 Linux 机器的 localhost 相同。 WSL VM 中的 2 个进程可以通过 localhost 进行通信。跨发行版 IPC 必须使用 host.docker.internal。可以在 WSL VM 中创建桥接器 - Docker 可以做到。

【讨论】:

【参考方案10】:

tldr;通过静态IP172.17.0.1访问主机

向主机发起 HTTP 请求:

    运行以下命令获取静态IP:ip addr show | grep "\binet\b.*\bdocker0\b" | awk 'print $2' | cut -d '/' -f 1

    将新 IP 添加到允许的主机

    使用刚刚在您的请求中找到的 IP 地址:req = requests.get('http://172.17.0.1:8000/api/YOUR_ENDPOINT')

【讨论】:

【参考方案11】:

对于 linux,我可以使用我尝试连接的服务名称,例如我的一个容器(php-fpm)正在尝试连接到 mysql,所以我使用 mysql 作为主机名,因为这是我的 docker-compose 中的服务名称

【讨论】:

这个问题是关于连接到主机系统,而不是同一个 docker-compose 环境中的另一个服务。 两件事:a)它是对潜在问题的正确答案(而不是使用 /etc/hosts 破解 DNS 解析)和 b)使用 docker 的内部来做简单的事情,比如访问暴露的端口是并且一直是不鼓励的。这就是 docker-compose 中的 -p 或“公开”所做的。我知道这个问题有点不同,但它源于另一个错误,通过模拟 /etc/hosts 刚刚被覆盖 - 未修复。

以上是关于什么是“host.docker.internal”的linux等价物的主要内容,如果未能解决你的问题,请参考以下文章

添加 8.8.8.8 DNS 条目后,Docker 映像停止解析 host.docker.internal

java.net.UnknownHostException:host.docker.internal:AWS EC2 上的名称或服务未知

spring boot cloud eureka windows 10 eureka在最新的docker升级后返回host.docker.internal作为客户端主机名

MySQL 数据库修改访问权限,不能使用ip连接mysql问题处理:Host ‘host.docker.internal‘ is not allowed to connect to this MySQ

未找到 RabbitMQ 指标

如何使用文件URI从运行springboot的docker镜像访问本地文件?