【问题标题】:How to share localhost between two different Docker containers?如何在两个不同的 Docker 容器之间共享 localhost?
【发布时间】:2017-09-18 18:09:22
【问题描述】:

我有两个不同的 Docker 容器,每个容器都有不同的镜像。容器中的每个应用程序都使用不冲突的端口。见docker-compose.yml

version: "2"

services:

  service_a:
    container_name: service_a.dev
    image: service_a.dev
    ports:
      - "6473:6473"
      - "6474:6474"
      - "1812:1812"
    depends_on:
      - postgres
    volumes:
      - ../configs/service_a/var/conf:/opt/services/service_a/var/conf

  postgres:
    container_name: postgres.dev
    hostname: postgres.dev
    image: postgres:9.6
    ports:
      - "5432:5432"
    volumes:
      - ../configs/postgres/scripts:/docker-entrypoint-initdb.d/

我可以从主机(Mac OS)成功地卷曲每个图像,例如curl -k https://localhost:6473/service_a/api/version 有效。我想做的是能够从service_a容器通过localhost引用postgres容器,就好像这两个容器是一个容器并且它们共享相同的localhost .我知道如果我在service_a 容器内使用主机名postgres.dev 是可能的,但我希望能够使用localhost。这可能吗?请注意,我不太精通网络或 Docker。

Mac 版本:10.12.4

Docker 版本:Docker 版本 17.03.0-ce,build 60ccb22

我之前已经做了很多研究,但找不到解决方案。 相关:https://forums.docker.com/t/localhost-and-docker-compose-networking-issue/23100/2

【问题讨论】:

  • 有几种(不同程度的 hackiness)方法,但你为什么要这样做?
  • 我再说一遍,你为什么要这样做?与localhost 混淆只会造成混乱。在同一个容器中运行这两个进程可以实现相同的效果,而无需 hackiness。
  • 我的用例是这样的:出于某些安全目的,这两个服务必须部署在同一主机上,因此现实世界中的service_a 将被配置为仅监听localhost/127.0.0.1。理想情况下,我会创建一个同时具有 postgres 和 service_a 的 Docker 映像,但这似乎不可行,因此我的方法在这里。

标签: docker


【解决方案1】:

正确的方法:不要使用 localhost。而是使用 docker 内置的 DNS 网络,并通过服务名称引用容器。您甚至不应该设置容器名称,因为这会破坏缩放。


不好的方法:如果您不想使用 docker 网络功能,那么您可以切换到主机网络,但这会关闭一个非常关键的功能和其他 docker 功能,例如将容器以自己的方式连接在一起的选项孤立的网络将不再起作用。使用该免责声明,结果将如下所示:

version: "2"

services:

  service_a:
    container_name: service_a.dev
    image: service_a.dev
    network_mode: "host"
    depends_on:
      - postgres
    volumes:
      - ../configs/service_a/var/conf:/opt/services/service_a/var/conf

  postgres:
    container_name: postgres.dev
    image: postgres:9.6
    network_mode: "host"
    volumes:
      - ../configs/postgres/scripts:/docker-entrypoint-initdb.d/

请注意,我删除了从容器到主机的端口发布,因为您不再处于容器网络中。而且我删除了主机名设置,因为您不应该从 docker 容器中更改主机本身的主机名。

您引用的链接论坛帖子显示了当这是一个 VM 时,主机无法以 localhost 的身份与容器通信。这是一个预期的限制,但容器本身将能够作为 localhost 相互通信。如果您使用基于 VirtualBox 的安装和 docker-toolbox,您应该能够通过 virtualbox IP 与容器通信。


真正错误的做法:滥用容器网络模式。该模式可用于调试容器网络问题和专门的用例,实际上不应该用于避免重新配置应用程序以使用 DNS。当你停止数据库时,你会破坏你的另一个容器,因为它会失去它的网络命名空间。

为此,您可能需要运行两个单独的 docker-compose.yml 文件,因为 docker-compose 会在执行任何操作之前检查网络是否存在。从 postgres 容器开始:

version: "2"
services:
  postgres:
    container_name: postgres.dev
    image: postgres:9.6
    ports:
      - "5432:5432"
    volumes:
      - ../configs/postgres/scripts:/docker-entrypoint-initdb.d/

然后你可以在同一个网络命名空间中创建第二个服务:

version: "2"
services:
  service_a:
    container_name: service_a.dev
    image: service_a.dev
    network_mode: "container:postgres.dev"
    ports:
      - "6473:6473"
      - "6474:6474"
      - "1812:1812"
    volumes:
      - ../configs/service_a/var/conf:/opt/services/service_a/var/conf

【讨论】:

  • 我认为这是正确的方法;不幸的是,Mac 的 Docker 似乎与 host 网络存在问题:forums.docker.com/t/should-docker-run-net-host-work/14215forums.docker.com/t/…
  • 论坛帖子指出了尝试从主机访问使用localhost的容器的问题。这个问题和这个答案涵盖了从容器到本地主机的容器。但我要重申,请不要这样做,如果它坏了,你可以保留所有的碎片。
【解决方案2】:

特别是对于 Mac 和本地测试期间,我设法使用 docker.for.mac.localhost 方法让多个容器工作。我记录了它http://nileshgule.blogspot.sg/2017/12/docker-tip-workaround-for-accessing.html

【讨论】:

  • 您的链接不再出现在 blogspot 上,并且代码(在现已删除的图像上共享)不再存在于重定向页面中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多