Compose 文件中的 --add-host=host.docker.internal:host-gateway 等效项是什么

s.k*_*s.k 49 linux docker docker-compose docker-network

从 Docker 版本20.10https://github.com/moby/moby/pull/40007)开始,有一个新的特殊字符串host-gateway,可以在--add-host运行标志中使用,以允许从 docker 容器内部直接连接到本地计算机在基于 Linux 的系统上。这非常好。

--add-host=host.docker.internal:host-gateway但是Compose 文件中的等价物是什么?

例如在:

$ docker run \
  --rm \
  --name postgres \
  -p "5433:5432" \
  -e POSTGRES_PASSWORD=**** \
  --add-host=host.docker.internal:host-gateway \
  -d postgres:14.1-bullseye
Run Code Online (Sandbox Code Playgroud)

相同的标志如何--add-host适合这个 Docker Compose 等效模板:

version: '3.9'

services:
  postgres:
    image: postgres:14.1-bullseye
    environment:
      POSTGRES_PASSWORD: ****
    ports:
      - "5433:5432"
Run Code Online (Sandbox Code Playgroud)

肯定不是:network_mode: host在服务级别(参见#Doc)。

s.k*_*s.k 83

实际的 Docker Compose 等效项是通过将相同的字符串附加到参数来实现的extra_hosts#Doc ) 来实现的,如下所示:

\n
version: \'3.9\'\n\nservices:\n  postgres:\n    image: postgres:14.1-bullseye\n    environment:\n      POSTGRES_PASSWORD: ****\n    ports:\n      - "5433:5432"\n    extra_hosts:\n      - "host.docker.internal:host-gateway"\n
Run Code Online (Sandbox Code Playgroud)\n

您可以看到它已成功映射到容器内部的docker0接口IP,例如:172.17.0.1

\n
$ docker-compose up -d\n$ docker-compose exec postgres bash\n
Run Code Online (Sandbox Code Playgroud)\n

然后,从容器内部:

\n
root@5864db7d7fba:/# apt update && apt -y install netcat\nroot@5864db7d7fba:/# nc -vz host.docker.internal 80\nConnection to host.docker.internal (172.17.0.1) 80 port [tcp/http] succeeded!\n
Run Code Online (Sandbox Code Playgroud)\n

(假设端口 80 没有docker0被主机上的防火墙关闭或限制为接口的 IP)。

\n

有关更多信息,请访问:
\n https://medium.com/@TimvanBaarsen/how-to-connect-to-the-docker-host-from-inside-a-docker-container-112b4c71bc66

\n

但是...请注意...\n

\n

警告\xe2\x9a\xa0\xef\xb8\x8f

\n

这通常总是与主机上接口172.17.0.1的 IP匹配。docker0因此,如果您使用 Compose 文件启动容器(因此,而不是使用docker run),则该容器将依赖于 Compose 服务构建期间创建的网络的可能性无限高。这个网络将使用一个随机的网关地址,172.xxx.0.1其形式肯定与172.17.0.1默认的 docker 网关不同,例如可以是172.22.0.1.

\n

例如,如果您仅显式授权连接到172.17.0.1主机上本地服务的端口,这可能会给您带来一些麻烦。\n事实上,无法从容器内部 ping 该服务的端口,正是因为这个不同分配的网关地址 ( 172.22.0.1)。

\n

因此,由于您无法提前知道 Compose 网络将具有哪个网关地址,因此我强烈建议您明智地network在 Compose 文件中构建自定义定义,例如:

\n
version: \'3.9\'\n\nnetworks:\n  network1:\n    name: my-network\n    attachable: true\n    ipam:\n      driver: default\n      config:\n        - subnet: 172.18.0.0/16\n          ip_range: 172.18.5.0/24\n          gateway: 172.18.0.1\n\nservices:\n  postgres:\n    image: postgres:14.1-bullseye\n    environment:\n      POSTGRES_PASSWORD: ****\n    ports:\n      - "5433:5432"\n    networks:\n      - network1\n
Run Code Online (Sandbox Code Playgroud)\n

如果需要,我还建议使用一些 IP 范围计算器工具,例如http://jodies.de/ipcalc?host=172.18.5.0&mask1=24&mask2=来帮助您完成该任务,特别是在使用CIDR表示法定义范围时。

\n

最后,旋转你的容器。并验证新指定的网关地址172.18.0.1是否已正确使用:

\n
$ docker inspect tmp_postgres_1  -f \'{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}\'\n172.18.0.1\n
Run Code Online (Sandbox Code Playgroud)\n

附加到它,安装netcat并验证:

\n
root@9fe8de220d44:/# nc -vz 172.18.0.1 80\nConnection to 172.18.0.1 80 port [tcp/http] succeeded!\n
Run Code Online (Sandbox Code Playgroud)\n

(您可能还需要相应地调整防火墙规则和/或本地服务允许的 IP,例如数据库)

\n

另一种解决方案

\n

bridge是使用连接到现有的默认网络docker network。为此,在启动容器后,运行以下命令:

\n
$ docker network connect bridge tmp_postgres_1\n
Run Code Online (Sandbox Code Playgroud)\n

现在,检查应该给你两个 IP;您设置的一个(如果有)或在容器创建期间由 docker 自动设置的一个,以及bridge

\n
$ docker inspect tmp_postgres_1 -f \'{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}\' \n172.17.0.1 172.18.0.1\n
Run Code Online (Sandbox Code Playgroud)\n

或者

\n

您可以跳过手动网络创建,并在 Compose 服务定义中直接告诉您bridge使用network_mode:以下标志加入网络:

\n
version: \'3.9\'\n\nservices:\n  postgres:\n    image: postgres:14.1-bullseye\n    environment:\n      POSTGRES_PASSWORD: ****\n    ports:\n      - "5433:5432"\n    # removed networks: and add this:\n    network_mode: bridge\n    extra_hosts:\n      - "host.docker.internal:host-gateway"\n
Run Code Online (Sandbox Code Playgroud)\n

现在,无论您使用Compose 文件中的docker network connect...方法还是标志,您通常都会成功地通过 Gatewaynetwork_mode:加入默认网络,这将允许您使用该网关 IP 连接到您的主机,可以通过键入其数值,或者如果设置,变量:bridge172.17.0.1host.docker.internal

\n
root@9fe8de220d44:/# nc -vz 172.18.0.1 80\nConnection to 172.18.0.1 80 port [tcp/http] succeeded!\nroot@9fe8de220d44:/# nc -vz 172.17.0.1 80\nConnection to 172.18.0.1 80 port [tcp/http] succeeded!\nroot@9fe8de220d44:/# nc -vz host.docker.internal 80\nConnection to host.docker.internal (172.17.0.1) 80 port [tcp/http] succeeded!\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x9a\xa0\xef\xb8\x8f 但是通过加入网络bridge,您还可以使容器与该网络上的所有其他容器(如果它们已发布端口)进行通信,反之亦然。因此,如果您需要明确地将其与其他容器分开,您最好不想这样做并坚持使用自己的自定义网络!

\n

如果事情不顺利怎么办?

\n

如果你在经过一些尝试后弄乱了你的 docker 网络,你可能会遇到这样的错误消息:

\n
Creating tmp_postgres_1 ... error\n\nERROR: for tmp_postgres_1  Cannot start service postgres: failed to create endpoint tmp_postgres_1 on network bridge: network 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486 does not exist\n\nERROR: for postgress  Cannot start service postgres: failed to create endpoint tmp_postgres_1 on network bridge: network 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486 does not exist\nERROR: Encountered errors while bringing up the project.\n
Run Code Online (Sandbox Code Playgroud)\n

即使895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486桥接网络确实存在,您也必须通过重新启动计算机或在最幸运的情况下通过 docker 服务来清理所有这些:

\n
Creating tmp_postgres_1 ... error\n\nERROR: for tmp_postgres_1  Cannot start service postgres: failed to create endpoint tmp_postgres_1 on network bridge: network 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486 does not exist\n\nERROR: for postgress  Cannot start service postgres: failed to create endpoint tmp_postgres_1 on network bridge: network 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486 does not exist\nERROR: Encountered errors while bringing up the project.\n
Run Code Online (Sandbox Code Playgroud)\n

(adocker networkd prune -f可能还不够)。

\n
\n

文档中的更多内容:
\n https://docs.docker.com/compose/networking/
\n https://docs.docker.com/compose/compose-file/compose-file-v3/#networks
\n https ://github.com/compose-spec/compose-spec/blob/master/spec.md#networks-top-level-element

\n
\n

在具有以下规格的主机上进行了测试:
\nUbuntu:18.04.6 LTS
\n内核:5.4.0-94-generic
\nDocker:20.10.12,内部版本 e91ed57
\nDocker Compose:1.27.4,内部版本 40524192

\n