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

时间:2016-06-29 00:13:58

标签: networking docker docker-compose

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

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

如何确保front中的容器可以向api中的容器发送请求?

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

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

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

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

但最终我正在照顾的是:

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

13 个答案:

答案 0 :(得分:190)

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

# front/docker-compose.yml
version: '2'
services:
  front:
    ...
    networks:
      - some-net
networks:
  some-net:
    driver: bridge

...

# api/docker-compose.yml
version: '2'
services:
  api:
    ...
    networks:
      - front_some-net
networks:
  front_some-net:
    external: true
  

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

然后他们可以使用服务名称相互交谈。从front开始,您可以ping api,反之亦然。

答案 1 :(得分:54)

只是对@ johnharris85的一个小小的调整,这是一个很好的答案, 当您运行泊坞窗撰写文件时," default"网络已创建 所以你可以把它作为外部网络添加到另一个撰写文件中:

# front/docker-compose.yml 
version: '2' 
  services:   
    front_service:
    ...

...

# api/docker-compose.yml
version: '2'
services:
  api_service:
    ...
    networks:
      - front_default
networks:
  front_default:
    external: true

对我而言,这种方法更适合,因为我没有第一个docker-compose文件并想与之通信。

答案 2 :(得分:44)

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

这现在有效:

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

networks:
  proxynet:
    name: custom_network

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

现在,你可以这样做:

version: "2"
services:
  web:
    image: hello-world
    networks:
      - my-proxy-net
networks:
  my-proxy-net:
    external:
      name: custom_network

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

我在文档中找不到任何引用但它有效!

答案 3 :(得分:22)

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

# api/docker-compose.yml

...

networks:
  default:
    external:
      name: front_default

请参阅docker撰写指南:using a pre existing network(参见底部)

答案 4 :(得分:7)

以前的帖子信息是正确的,但它没有关于如何链接容器的详细信息,这些容器应该连接为“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

这是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

答案 5 :(得分:3)

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

networks:
  default:
    name: my-app
  

以上假设您将version设置为3.5(如果他们不在4 +内弃用,则为以上)。

其他答案也有相同的说法;这是一个简化的摘要。

答案 6 :(得分:2)

您可以在所有包含.env的项目中添加COMPOSE_PROJECT_NAME=somename文件。

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

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

答案 7 :(得分:1)

我会确保所有容器docker-compose通过同时将它们组合在同一个网络中,使用:

docker compose --file ~/front/docker-compose.yml --file ~/api/docker-compose.yml up -d

答案 8 :(得分:1)

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

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

例如,我们有两个API scoringnerScoring api需要向ner api发送请求以处理输入请求。为了做到这一点,他们俩都假定共享同一网络。

注意:每个容器都有其自己的网络,该网络是在docker内部运行应用程序时自动创建的。例如,将创建像ner_default这样的ner api网络,并将评分api网络命名为scoring default。此解决方案适用于版本“ 3”。

在上述情况下,我的计分api要与ner api通信,那么我将添加以下几行。这意味着每当我为ner api创建容器时,它就会自动添加到scoring_default网络。

networks:
  default:
      external:
        name: scoring_default

ner / docker-compose.yml

version: '3'
services:
  ner:
    build: .
    ...

networks:
  default:
      external:
        name: scoring_default

scoring / docker-compose.yml

version: '3'
services:
  api:
    build: .
    ...

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

  

泊坞窗检查scoring_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": ""
    },
    ...
}

答案 9 :(得分:0)

version: '2'
services:
  bot:
    build: .
    volumes:
      - '.:/home/node'
      - /home/node/node_modules
    networks:
      - my-rede
    mem_limit: 100m
    memswap_limit: 100m
    cpu_quota: 25000
    container_name: 236948199393329152_585042339404185600_bot
    command: node index.js
    environment:
      NODE_ENV: production
networks:
  my-rede:
    external:
      name: name_rede_externa

答案 10 :(得分:0)

  

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

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

第二个docker-compose.yml

docker network ls

答案 11 :(得分:0)

另一种选择是使用“ docker-compose”运行第一个模块,检查与该模块相关的ip,然后将第二个模块与先前的网络(例如外部)连接,并指向内部ip

示例 app1-在服务行中创建的新网络,标记为外部:底部为true app2-向上显示由app1创建的“新网络”,在底部标记为external:在true,然后在配置中进行设置以连接app1在该网络中拥有的ip。

有了这个,你应该能够互相交谈

*此方法仅用于本地测试,以免进行过于复杂的配置 **我知道这是非常“修补方式”,但对我有用,我认为其他人可以利用此方法很简单

答案 12 :(得分:0)

如果您是

  • 试图在不同的docker-compose项目不想使用相同的网络的两个容器之间进行通信(因为假设它们将具有PostgreSQL或Redis容器相同的端口上,您最好不要更改这些端口,并且不要在同一网络上使用它)
  • 在本地进行开发,并且希望模仿两个docker compose项目
  • 之间的通信
  • 在本地主机上运行两个docker-compose项目
  • 特别开发Django应用程序或Django Rest Framework(drf)API,并在某些暴露的端口上的容器内运行应用程序
  • 尝试在两个容器之间进行通信时获取Connection refused

您想

  • 容器api_aapi_b通信(反之亦然),而没有相同的“ docker网络”

(下面的示例)

您可以将第二个容器的“主机”用作计算机的IP和从Docker容器内部映射的端口。您可以使用以下脚本获取计算机的IP(来自:Finding local IP addresses using Python's stdlib):

import socket
def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP

示例:

project_api_a/docker-compose.yml

networks:
  app-tier:
    driver: bridge

services:
  api:
    container_name: api_a
    image: api_a:latest
    depends_on:
      - postgresql
    networks:
      - app-tier

api_a容器中,您正在运行Django应用程序: manage.py runserver 0.0.0.0:8000

和其他项目中的第二个docker-compose.yml:

project_api_b/docker-compose-yml

networks:
  app-tier:
    driver: bridge

services:
  api:
    container_name: api_b
    image: api_b:latest
    depends_on:
      - postgresql
    networks:
      - app-tier

api_b容器中,您正在运行Django应用程序: manage.py runserver 0.0.0.0:8001

并尝试从容器api_aapi_b连接,那么api_b容器的URL将为: http://<get_ip_from_script_above>:8001/

如果您要使用两个(三个或更多)docker-compose项目,并且很难为所有项目提供通用网络,这将是非常有价值的-这是一个很好的解决方法和解决方案