首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么等价于--add=host.docker.inside:复合文件中的主机-网关

什么等价于--add=host.docker.inside:复合文件中的主机-网关
EN

Stack Overflow用户
提问于 2022-01-15 22:18:22
回答 1查看 19.7K关注 0票数 22

从Docker 20.10 (https://github.com/moby/moby/pull/40007)开始,有一个新的特殊字符串host-gateway,它可以在--add-host run标志中使用,以便在基于Linux的系统上从停靠容器内部直接连接到本地机器。这很不错。

但是,在撰写文件中,--add-host=host.docker.internal:host-gateway的等效性是什么呢?

例如:

代码语言:javascript
复制
$ 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中,构成等效模板:

代码语言:javascript
复制
version: '3.9'

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

当然不是:服务级别的network_mode: host (参见#Doc)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-15 22:18:22

通过将相同的字符串附加到extra_hosts参数(#Doc)中,可以实现实际的Docker等效:

代码语言:javascript
复制
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 ),例如:

代码语言:javascript
复制
$ docker-compose up -d
$ docker-compose exec postgres bash

然后,从容器内部:

代码语言:javascript
复制
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

但是..。小心..。

警告⚠️

这通常总是与主机上的172.17.0.1接口的docker0 IP相匹配。因此,如果使用复合文件(所以,而不是使用docker run)拆分容器,则该容器依赖于在构建组合服务期间创建的网络的可能性是无限大的。这个网络将使用表单172.xxx.0.1的随机网关地址,这肯定与172.17.0.1默认的停靠网关不同,例如,可以是172.22.0.1

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

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

代码语言:javascript
复制
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符号定义范围时。

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

代码语言:javascript
复制
$ docker inspect tmp_postgres_1  -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}'
172.18.0.1

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

代码语言:javascript
复制
root@9fe8de220d44:/# nc -vz 172.18.0.1 80
Connection to 172.18.0.1 80 port [tcp/http] succeeded!

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

另一种解决办法

是使用bridge连接到现有的默认docker network网络。为了做到这一点,在旋转容器之后,运行以下命令:

代码语言:javascript
复制
$ docker network connect bridge tmp_postgres_1

现在,检查应该为您提供两个IP;一个是您在容器创建过程中设置的一个(如果有的话),另一个是由码头自动设置的bridge IP:

代码语言:javascript
复制
$ docker inspect tmp_postgres_1 -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' 
172.17.0.1 172.18.0.1

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

代码语言:javascript
复制
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"

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

代码语言:javascript
复制
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网络,您的容器还可以与该网络上的所有其他容器通信(如果它们已经发布了端口),反之亦然。因此,如果您需要清楚地将它与这些其他容器分开,您最好不要这样做,只使用它自己的自定义网络!

万一出了什么事怎么办?

如果您在一些试验后破坏了码头网络,您可能会面临这样的错误信息:

代码语言:javascript
复制
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桥网络确实存在,您必须通过重新启动计算机或在最幸运的情况下,通过以下方式清除所有这些:

代码语言:javascript
复制
$ 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-泛型

Docker: 20.10.12,构建e91ed57

码头组成: 1.27.4,构建40524192

票数 31
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70725881

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档