我有两个独立的docker-compose。Yml文件在两个不同的文件夹:

~/front/docker-compose.yml ~/api/docker-compose.yml

我如何确保前面的容器可以在api中向容器发送请求?

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

目前,我结束了一个docker检查my_api_container_id,并查看输出中的网关。它是有效的,但问题是这个IP是随机分配的,所以我不能依赖它。

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

我可以使用docker-compose将一个固定的IP地址归属于特定的容器吗?

但最终我所追求的是:

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


当前回答

对于使用另一个docker-compose网络,你只需要做这些(在docker-compose之间共享网络): 使用up -d运行第一个docker-compose项目 找到第一个docker的网络名称-通过:docker network ls(它包含根目录项目的名称) 然后在第二个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

其他回答

您只需要确保希望相互通信的容器位于同一网络上。网络是一流的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_

然后,它们可以使用服务名相互通信。从前面你可以做ping api,反之亦然。

如果你是

trying to communicate between two containers from different docker-compose projects and don't want to use the same network (because let's say they would have PostgreSQL or Redis container on the same port and you would prefer to not changing these ports and not use it at the same network) developing locally and want to imitate communication between two docker compose projects running two docker-compose projects on localhost developing especially Django apps or Django Rest Framework (drf) API and running app inside container on some exposed port getting Connection refused while trying to communicate between two containers

你想要

容器api_a与api_b通信(反之亦然)没有相同的“docker网络”

(下面的例子)

你可以使用第二个容器的“host”作为你的计算机的IP和端口,从Docker容器内部映射。你可以用这个脚本获取你计算机的IP地址(从:使用Python的stdlib查找本地IP地址):

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

第二种是船坞结构。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_a连接到api_b,然后api_b容器的URL将是: http:// < get_ip_from_script_above >: 8001 /

如果你正在使用超过两个(三个或更多)docker-compose项目,并且很难为所有这些项目提供公共网络,那么它就特别有价值——这是一个很好的解决方案和解决方案

要连接两个docker-compose,你需要一个网络,把两个docker-compose都放在这个网络中, 你可以用docker来创建网络,

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

在两个docker-compose文件中放入下面的行

networks:
   net-for-alpine:
     name: test-db-net

注意: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

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

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

docker exec -it alpine sh 
      

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

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

or

ping pgsql

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

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

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

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

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

networks:
  default:
      external:
        name: scoring_default

ner/docker-compose.yml

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

networks:
  default:
      external:
        name: scoring_default

得分/ docker-compose.yml

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

我们可以看到上面的容器现在是同一个名为scoring_default的网络的一部分:

Docker检查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": ""
    },
    ...
}

我有一个类似的例子,我正在使用单独的docker-compose文件,在一个覆盖网络的docker swarm上工作,我所要做的就是改变网络参数:

第一个docker-compose.yaml

version: '3.9'
.
.
.

networks:
  net:
    driver: overlay
    attachable: true
docker-compose -p app up

因为我已经使用-p将应用程序名称指定为app,初始网络将是app_net。 现在,为了运行另一个docker-compose与多个使用同一网络的服务,你需要这样设置:

第二个docker-compose.yaml

version: '3.9'
.
.
.
networks:
  net-ref:
    external: true
    name: app_net
docker stack deploy -c docker-compose.yml mystack

无论给堆栈取什么名字,网络都不会受到影响,它总是引用名为app_net的现有外部网络。

PS:确保检查docker-compose版本是很重要的。