多个docker-compose项目之间的通信

Jiv*_*van 191 networking docker docker-compose

docker-compose.yml在两个不同的文件夹中有两个单独的文件:

  • 〜/前/搬运工-compose.yml
  • 〜/ API /搬运工-compose.yml

如何确保容器中的容器~/front/docker-compose.yml可以向容器发送请求~/api/docker-compose.yml

我知道front可以使用api单个容器设置该选项,以便可以为此容器分配特定的IP地址,但似乎此选项在使用时不可用--default-gateway.

目前我最终做了一个docker run并查看输出中的网关.它有效,但问题是这个IP是随机归因的,所以我不能依赖它.

因此,这个问题的另一种形式可能是:

  • 我可以使用docker-compose将固定IP地址归属到特定容器吗?

但最后我要照顾的是:

  • 两个不同的docker-compose项目如何相互通信?

joh*_*s85 247

您只需要确保要彼此通信的容器位于同一网络上.网络是一流的docker构造,并不是特定的组合.

# front/docker-compose.yml
version: '2'
services:
  front:
    ...
    networks:
      - some-net
networks:
  some-net:
    driver: bridge
Run Code Online (Sandbox Code Playgroud)

...

# api/docker-compose.yml
version: '2'
services:
  api:
    ...
    networks:
      - front_some-net
networks:
  front_some-net:
    external: true
Run Code Online (Sandbox Code Playgroud)

注意:您的应用程序的网络名称基于"项目名称",该名称基于其所在目录的名称,在这种情况下front_添加了前缀

然后,他们可以使用服务名称相互通信.从front你可以做到ping api,反之亦然.

  • 请注意,网络的“front_”前缀是从其运行的文件夹中自动创建的。因此,如果您的第一个 docker-compose 文件位于“example/docker-compose.yml”中,它将被称为“example_default”。 (5认同)
  • @SteveB - 请注意,name 属性仅适用于 docker-compose 文件版本 3.5 及更高版本 (5认同)
  • 罗伯特·莫斯卡尔(Robert Moskal),只有当你破解你的码头主机的ip到容器中时才会这样.最好让他们在一个常见的docker定义的网络上进行通信. (3认同)
  • 只是好奇,如果我们有相同的服务名称但在不同的网络上会发生什么,调用者容器是否可以更明确地了解它想要使用哪个网络来调用特定服务? (3认同)
  • Jivan 那不是解决方案。您的容器不需要了解有关主机的任何信息或进行类似的操作。我的回答很简短,我已经更新了更多细节。 (2认同)
  • 您也可以使用`name`属性为网络提供名称,这将禁用使用项目名称自动添加前缀。然后,任何一个项目都可以使用该网络并自动创建它(如果尚不存在)。 (2认同)

Tal*_*ffe 63

只是对@ johnharris85的一个很好的答案,当您运行docker compose文件时,default会创建一个" "网络,这样您就可以将其作为外部网络添加到其他撰写文件中:

# front/docker-compose.yml 
version: '2' 
  services:   
    front_service:
    ...
Run Code Online (Sandbox Code Playgroud)

...

# api/docker-compose.yml
version: '2'
services:
  api_service:
    ...
    networks:
      - front_default
networks:
  front_default:
    external: true
Run Code Online (Sandbox Code Playgroud)

对我来说这种方法更合适,因为我没有拥有第一个docker-compose文件并希望与之通信.


cst*_*ton 54

更新:从撰写文件版本3.5开始:

这现在有效:

version: "3.5"
services:
  proxy:
    image: hello-world
    ports:
      - "80:80"
    networks:
      - proxynet

networks:
  proxynet:
    name: custom_network
Run Code Online (Sandbox Code Playgroud)

docker-compose up -d将加入一个名为'custom_network'的网络.如果它不存在,它将被创建!

现在,你可以这样做:

root@ubuntu-s-1vcpu-1gb-tor1-01:~# docker-compose up -d
Creating network "custom_network" with the default driver
Creating root_proxy_1 ... done
Run Code Online (Sandbox Code Playgroud)

这将创建一个将位于外部网络上的容器.

我在文档中找不到任何参考但是它有效!

  • @slashdottir 您可以**不**在第二个服务中将网络标记为外部网络,如果它尚不存在,则会创建它。 (6认同)
  • 以下是文档中的参考文献:https://docs.docker.com/compose/networking/#use-a-pre-existing-network (4认同)
  • 谢谢 !效果很好 (3认同)
  • 第一个服务(上面的代理)创建网络。第二个示例中的语法将其连接起来。 (3认同)
  • 确实有效。我只是用最新的docker compose旋转了DO滴。我已将示例编辑为实际的工作示例。 (2认同)
  • 就我而言,事实证明这是比接受的答案更合适的解决方案。外部网络的问题是,它需要按预定义的顺序启动容器。对于我的客户来说,这是不可接受的。命名网络(自 3.5 起)被证明是完美的解决方案。谢谢。 (2认同)

Wiq*_*iqi 42

每个人都解释得很好,所以我将通过一个简单的解释来添加必要的代码。

使用在 docker-compose 外部创建的网络(“外部”网络), docker-compose版本为3.5+

进一步的解释可以在这里找到。

第一个 docker-compose.yml文件应定义名称giveItANamePlease如下的网络。

networks:
  my-network:
    name: giveItANamePlease
    driver: bridge
Run Code Online (Sandbox Code Playgroud)

第一个文件的服务docker-compose.yml可以使用网络,如下:

networks:
  - my-network
Run Code Online (Sandbox Code Playgroud)

第二个 docker-compose文件中,我们需要使用第一个文件中使用的网络名称来代理网络docker-compose,在本例中为giveItANamePlease

networks:
  my-proxy-net:
    external:
      name: giveItANamePlease
Run Code Online (Sandbox Code Playgroud)

现在您可以my-proxy-net在第二个文件的服务中使用docker-compose.yml,如下所示。

networks:
  - my-proxy-net
Run Code Online (Sandbox Code Playgroud)

  • 最后一个现代/易于使用的答案 (5认同)
  • 使第二个文件中的“networks”部分与第一个文件匹配(删除对“external”的引用),哪个项目先启动并不重要(允许自动创建网络) (3认同)

ded*_*dek 22

所有容器api都可以通过以下配置加入front 默认网络:

# api/docker-compose.yml

...

networks:
  default:
    external:
      name: front_default
Run Code Online (Sandbox Code Playgroud)

请参阅docker撰写指南:使用预先存在的网络(参见底部)


Gae*_*ael 18

这么多答案!

首先,避免在服务和网络等实体名称中使用连字符。它们会导致名称解析问题。

示例:my-api行不通。myapi或者api会起作用。

对我有用的是:

# api/docker-compose.yml
version: '3'

services:
  api:
    container_name: api
    ...
    ports:
      - 8081:8080
    networks:
      - mynetwork

networks:
  mynetwork:
    name: mynetwork
Run Code Online (Sandbox Code Playgroud)

# front/docker-compose.yml
version: '3'

services:
  front:
    container_name: front
    ...
    ports:
      - 81:80
    networks:
      - mynetwork

networks:
  mynetwork:
    name: mynetwork
Run Code Online (Sandbox Code Playgroud)

注意:我添加了端口来显示服务如何相互访问以及如何从主机访问它们。

重要提示:如果您未指定网络namedocker-compose我们将为您制作一个网络。docker_compose.yml它使用文件所在文件夹的名称。在本例中:api_mynetworkfront_mynetwork。这将阻止容器之间的通信,因为它们将在不同的网络上使用非常相似的名称。

请注意,两个文件中的网络定义完全相同,因此您可以先启动任一服务,它就会工作。无需指定哪个是外部的,docker-compose我们将负责为您管理。

来自主机

您可以使用中定义的已发布端口来访问任一容器docker-compose.yml

您可以访问 Front 容器:curl http://localhost:81

您可以访问 API 容器:curl http://localhost:8081

来自 API 容器

您可以使用原始端口(而不是您发布的端口)访问 Front 容器docker-compose.yml

例子:curl http://front:80

从前面的容器

您可以使用原始端口(而不是您发布的端口)访问 API 容器docker-compose.yml

例子:curl http://api:8080


小智 10

以前的帖子信息是正确的,但它没有关于如何链接容器的详细信息,这些容器应该连接为"external_links".

希望这个例子让你更清楚:

  • 假设您有app1/docker-compose.yml,有两个服务(svc11和svc12),app2/docker-compose.yml有两个以上的服务(svc21和svc22),并且假设您需要以交叉方式连接:

  • svc11需要连接到svc22的容器

  • svc21需要连接到svc11的容器.

所以配置应该是这样的:

这是app1/docker-compose.yml:


version: '2'
services:
    svc11:
        container_name: container11
        [..]
        networks:
            - default # this network
            - app2_default # external network
        external_links:
            - container22:container22
        [..]
    svc12:
       container_name: container12
       [..]

networks:
    default: # this network (app1)
        driver: bridge
    app2_default: # external network (app2)
        external: true
Run Code Online (Sandbox Code Playgroud)

这是app2/docker-compose.yml:


version: '2'
services:
    svc21:
        container_name: container21
        [..]
        networks:
            - default # this network (app2)
            - app1_default # external network (app1)
        external_links:
            - container11:container11
        [..]
    svc22:
       container_name: container22
       [..]

networks:
    default: # this network (app2)
        driver: bridge
    app1_default: # external network (app1)
        external: true
Run Code Online (Sandbox Code Playgroud)


emy*_*ler 9

从 Compose 1.18(规范 3.5)开始,您可以使用您自己的自定义名称为您需要的所有 Compose YAML 文件覆盖默认网络。就像将以下内容附加到它们一样简单:

networks:
  default:
    name: my-app
Run Code Online (Sandbox Code Playgroud)

以上假设您已version设置为3.5(或以上,如果他们在 4+ 中不弃用它)。

其他答案也指出了同样的问题;这是一个简化的总结。

  • 添加到 @gustavz 的上述评论,使用“default”作为网络标识符允许不需要指定在服务中使用的网络。默认网络**名称**“my-app”可以是任何有助于对多个 Compose 服务进行分组的名称。 (2认同)

Nom*_*uks 8

更新:从 docker-compose 文件版本 3.5 开始:

我遇到了一个类似的问题,我通过在我的一个 docker-compose.yml 项目中添加一个小的更改来解决它。

例如,我们有两个 APIscoringner. ScoringAPI 需要向 API 发送请求以ner处理输入请求。为了做到这一点,他们都应该共享同一个网络。

注意:每个容器都有自己的网络,它是在 docker 中运行应用程序时自动创建的。例如,将创建 ner API 网络,并将ner_default评分 API 网络命名为scoring default. 此解决方案适用于版本:'3'。

在上面的场景中,我的评分 API 想要与 ner API 通信,然后我将添加以下几行。这意味着每当我为 ner API 创建容器时,它就会自动添加到评分默认网络中。

networks:
  default:
      external:
        name: scoring_default
Run Code Online (Sandbox Code Playgroud)

ner/docker-compose.yml

version: '3'
services:
  ner:
    container_name: "ner_api"
    build: .
    ...

networks:
  default:
      external:
        name: scoring_default
Run Code Online (Sandbox Code Playgroud)

评分/docker-compose.yml

version: '3'
services:
  api:
    build: .
    ...
Run Code Online (Sandbox Code Playgroud)

我们可以看到上述容器现在如何成为scoring_default使用以下命令调用的同一网络的一部分 :

码头工人检查 score_default

{
    "Name": "scoring_default",
        ....
    "Containers": {
    "14a6...28bf": {
        "Name": "ner_api",
        "EndpointID": "83b7...d6291",
        "MacAddress": "0....",
        "IPv4Address": "0.0....",
        "IPv6Address": ""
    },
    "7b32...90d1": {
        "Name": "scoring_api",
        "EndpointID": "311...280d",
        "MacAddress": "0.....3",
        "IPv4Address": "1...0",
        "IPv6Address": ""
    },
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 两个应用程序都可以使用它们的名称来相互通信。例如,评分应用程序可以使用“http://ner_api:port/extract”调用 ner 应用程序,反之亦然 (2认同)

Exa*_*313 6

您可以.env在所有包含COMPOSE_PROJECT_NAME=somename.

COMPOSE_PROJECT_NAME覆盖用于命名资源的前缀,因此您的所有项目都将用作somename_default其网络,从而使服务可以像在同一项目中一样相互通信。

注意:您将收到有关从其他项目创建的“孤立”容器的警告。


Ali*_*aji 5

要使用另一个 docker-compose 网络,您只需执行以下操作(在 docker-compose 之间共享网络):

  1. 运行第一个 docker-compose 项目up -d
  2. 通过以下方式找到第一个docker-compose的网络名称:(docker network ls它包含根目录项目的名称)
  3. 然后在第二个 docker-compose 文件中通过下面的结构使用该名称。

第二个 docker-compose.yml

version: '3'
services:
  service-on-second-compose:  # Define any names that you want.
    .
    .
    .
    networks:
      - <put it here(the network name that comes from "docker network ls")>

networks:
  - <put it here(the network name that comes from "docker network ls")>:
    external: true
Run Code Online (Sandbox Code Playgroud)


小智 5

要连接两个 docker-compose,您需要一个网络并将两个 docker-compose 放入该网络中,您可以使用docker network create name-of-network创建 netwrok ,

或者您可以简单地将网络声明放在docker-compose 文件的网络选项中,当您运行 docker-compose (docker-compose up) 时,网络将自动创建。

将以下行放入两个 docker-compose 文件中

networks:
   net-for-alpine:
     name: test-db-net
Run Code Online (Sandbox Code Playgroud)

注意:net-for-alpine是网络的内部名称,它将在 docker-compose 文件内部使用,可以不同, test-db-net是网络的外部名称,在两个 docker-compose 中必须相同文件。

假设我们有 docker-compose.db.yml 和 docker-compose.alpine.yml

docker-compose.apline.yml 将是:

version: '3.8'

services:

  alpine:
    image: alpine:3.14
    container_name: alpine
    networks:
      - net-for-alpine
  
    # these two command keeps apline container running
    stdin_open: true # docker run -i
    tty: true # docker run -t



networks:
  net-for-alpine:
    name: test-db-net
Run Code Online (Sandbox Code Playgroud)

docker-compose.db.yml 将是:

version: '3.8'

services:

  db:
    image: postgres:13.4-alpine
    container_name: psql
    networks:
      - net-for-db
  
networks:
  net-for-db:
    name: test-db-net
Run Code Online (Sandbox Code Playgroud)

要测试网络,请进入 alpine 容器

docker exec -it alpine sh 
      
Run Code Online (Sandbox Code Playgroud)

然后使用以下命令可以检查网络

# if it returns 0 or see nothing as a result, network is established
nc -z psql (container name)  
Run Code Online (Sandbox Code Playgroud)

或者

ping pgsql
Run Code Online (Sandbox Code Playgroud)