【问题标题】:What is the equivalent of --add-host=host.docker.internal:host-gateway in a Compose file什么是 Compose 文件中的 --add-host=host.docker.internal:host-gateway 的等价物
【发布时间】:2022-02-08 05:32:54
【问题描述】:

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

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

例如在:

$ docker run \
  --rm \
  --name postgres \
  -p "5433:5432" \
  -e POSTGRES_PASSWORD=**** \
  --add-host=host.docker.internal:host-gateway \
  -d postgres:14.1-bullseye

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

version: '3.9'

services:
  postgres:
    image: postgres:14.1-bullseye
    environment:
      POSTGRES_PASSWORD: ****
    ports:
      - "5433:5432"

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

【问题讨论】:

    标签: linux docker docker-compose docker-networking


    【解决方案1】:

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

    version: '3.9'
    
    services:
      postgres:
        image: postgres:14.1-bullseye
        environment:
          POSTGRES_PASSWORD: ****
        ports:
          - "5433:5432"
        extra_hosts:
          - "host.docker.internal:host-gateway"
    

    你可以看到它已经从你的容器内部成功映射到docker0接口的IP,这里是172.17.0.1,例如:

    $ docker-compose up -d
    $ docker-compose exec postgres bash
    

    然后,从容器内部:

    root@5864db7d7fba:/# apt update && apt -y install netcat
    root@5864db7d7fba:/# nc -vz host.docker.internal 80
    Connection to host.docker.internal (172.17.0.1) 80 port [tcp/http] succeeded!
    

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

    可以在此处找到更多信息:
    https://medium.com/@TimvanBaarsen/how-to-connect-to-the-docker-host-from-inside-a-docker-container-112b4c71bc66

    但是……当心……

    警告⚠️

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

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

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

    version: '3.9'
    
    networks:
      network1:
        name: my-network
        attachable: true
        ipam:
          driver: default
          config:
            - subnet: 172.18.0.0/16
              ip_range: 172.18.5.0/24
              gateway: 172.18.0.1
    
    services:
      postgres:
        image: postgres:14.1-bullseye
        environment:
          POSTGRES_PASSWORD: ****
        ports:
          - "5433:5432"
        networks:
          - network1
    

    如果需要,我还建议使用一些 IP 范围计算器工具,例如 http://jodies.de/ipcalc?host=172.18.5.0&mask1=24&mask2= 来帮助自己完成这项任务,尤其是在使用 CIDR 符号定义范围时。

    最后,启动您的容器。并验证新指定的Gateway地址172.18.0.1是否被正确使用:

    $ docker inspect tmp_postgres_1  -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}'
    172.18.0.1
    

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

    root@9fe8de220d44:/# nc -vz 172.18.0.1 80
    Connection to 172.18.0.1 80 port [tcp/http] succeeded!
    

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

    另一种解决方案

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

    $ docker network connect bridge tmp_postgres_1
    

    现在,检查应该给你两个 IP;您设置的那个(如果有的话)或者在容器创建过程中由 docker 自动设置的那个,以及bridge IP:

    $ docker inspect tmp_postgres_1 -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' 
    172.17.0.1 172.18.0.1
    

    或者

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

    version: '3.9'
    
    services:
      postgres:
        image: postgres:14.1-bullseye
        environment:
          POSTGRES_PASSWORD: ****
        ports:
          - "5433:5432"
        # removed networks: and add this:
        network_mode: bridge
        extra_hosts:
          - "host.docker.internal:host-gateway"
    

    现在,无论您是在 Compose 文件中使用 docker network connect... 方法还是 network_mode: 标志,您通常都会成功地将默认 bridge 网络与网关 172.17.0.1 连接起来,这将允许您使用该网关 IP连接到你的主机,或者通过输入它的数值,或者如果设置,变量host.docker.internal

    root@9fe8de220d44:/# nc -vz 172.18.0.1 80
    Connection to 172.18.0.1 80 port [tcp/http] succeeded!
    root@9fe8de220d44:/# nc -vz 172.17.0.1 80
    Connection to 172.18.0.1 80 port [tcp/http] succeeded!
    root@9fe8de220d44:/# nc -vz host.docker.internal 80
    Connection to host.docker.internal (172.17.0.1) 80 port [tcp/http] succeeded!
    

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

    如果出现问题怎么办?

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

    Creating tmp_postgres_1 ... error
    
    ERROR: for tmp_postgres_1  Cannot start service postgres: failed to create endpoint tmp_postgres_1 on network bridge: network 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486 does not exist
    
    ERROR: for postgress  Cannot start service postgres: failed to create endpoint tmp_postgres_1 on network bridge: network 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486 does not exist
    ERROR: Encountered errors while bringing up the project.
    

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

    $ sudo service docker restart
    

    docker networkd prune -f 可能还不够)。


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


    在具有以下规格的主机上测试:
    Ubuntu:18.04.6 LTS
    内核:5.4.0-94-generic
    Docker:20.10.12,构建 e91ed57
    Docker Compose:1.27.4,构建 40524192

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-19
    • 2020-07-01
    • 2018-10-25
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    相关资源
    最近更新 更多