複数のdocker-composeプロジェクト間の通信


253

docker-compose.yml2つの異なるフォルダーに2 つの個別のファイルがあります。

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

のコンテナーがのコンテナーにfrontリクエストを送信できることを確認するにはどうすればよいapiですか?

個別のコンテナ--default-gatewayを使用docker runしてオプションを設定できるため、このコンテナに特定のIPアドレスを割り当てることができることは知っていますが、を使用している場合、このオプションは使用できないようですdocker-compose

現在、私はa docker inspect my_api_container_idを実行して、出力でゲートウェイを確認しています。機能しますが、問題はこのIPがランダムに割り当てられるため、信頼できないことです。

したがって、この質問の別の形式は次のようになります。

  • docker-composeを使用して特定のコンテナに固定IPアドレスを割り当てることはできますか?

しかし、最終的に私が気にしているのは:

  • 2つの異なるdocker-composeプロジェクトが互いに通信するにはどうすればよいですか?

4
私は今日これをもう一度調べました。開発者たちはついに、任意のネットワーク命名を容認し、許可しました。構成ファイルバージョン3.5を使用すると、「ネットワーク」キーの下でデフォルトネットワークの名前を指定できます。それは...存在しない場合、これは通常のプロジェクト名の接頭辞のない名前のネットワークを作成します
cstrutton

回答:


325

互いに通信したいコンテナが同じネットワーク上にあることを確認する必要があるだけです。ネットワークは一流の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
Jivanは非解決策です。コンテナはホストについて何も知る必要がなく、そのように操作される必要もありません。私の答えはかなり短かったが、詳細を更新した。
johnharris85

3
Robert Moskalは、DockerホストのIPをコンテナにハッキングする場合にのみ使用します。Dockerで定義された一般的なネットワークで通信する方がよいでしょう。
johnharris85

2
ネットワークの "front_"プレフィックスは、その実行フォルダーから自動的に作成されることに注意してください。したがって、最初のdocker-composeファイルが「example / docker-compose.yml」にある場合は、代わりに「example_default」と呼ばれます。
AngryUbuntuNerd

7
nameプロパティを使用してネットワークに名前を提供することもできます。これにより、プロジェクト名の自動プリペンドが無効になります。その後、どちらのプロジェクトもそのネットワークを使用して、まだ存在しない場合は自動的に作成できます。
SteveB

2
@SteveB-nameプロパティはdocker-composeファイルバージョン3.5以降でのみ機能することに注意してください
kramer65

78

@ johnharris85のすばらしい答えのほんの少しの説明ですが、Docker構成ファイルを実行すると、「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ファイルを所有しておらず、それと通信したかったため、このアプローチの方が適していました。


この外部ネットワークに静的IPを割り当てる正しい方法をさまようだけです。私は中にそれを行うことがうまく管理services:sintaxがされるだろう、タグnetworks:その後、入れ子になったfront_default::私たちの巣静的IP当時と- (「」削除)ipv4_address: '172.20.0.44'
ジュニアMayhé

76

更新:作成ファイルバージョン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

これにより、外部ネットワーク上にあるコンテナが作成されます。

ドキュメントにはまだ参照がありませんが、動作します!


2つのサービスを特定の順序で開始する必要がありますか?どちらかを開始できますか?最初の1つがネットワークを作成し、2番目がそれに参加しますか?
slashdottir

4
最初のサービス(上記のプロキシ)がネットワークを作成します。2番目の例の構文はそれを結合します。
cstrutton

2
@slashdottir 2番目のサービスでネットワークを外部としてマークすることできません。ネットワークがまだ存在しない場合は作成されます。
SteveB

2
それは動作します。最新のdocker composeでDOドロップレットをスピンアップしました。例を実際の作業例に編集しました。
cstrutton

1
私の場合、これは受け入れられた答えよりも適切なソリューションであることがわかりました。外部ネットワークの問題は、事前定義された順序でコンテナーを開始する必要があることでした。私のクライアントにとって、これは受け入れられませんでした。名前付きネットワーク(3.5以降)は完璧なソリューションであることが判明しました。ありがとう。
イゴール

24

のすべてのコンテナは、次の構成でデフォルトネットワークにapi参加できfront ます

# api/docker-compose.yml

...

networks:
  default:
    external:
      name: front_default

docker composeガイドを参照してください:既存のネットワークの使用(下部を参照)


12

以前の投稿情報は正しいですが、「external_links」として接続する必要があるコンテナのリンク方法の詳細はありません。

この例があなたにもっと明確になることを願っています:

  • app1 / docker-compose.ymlに2つのサービス(svc11とsvc12)があり、app2 / docker-compose.ymlにさらに2つのサービス(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

6

Compose 1.18(仕様3.5)以降、必要なすべてのCompose YAMLファイルに独自のカスタム名を使用して、デフォルトネットワークをオーバーライドできます。それらに以下を追加するのと同じくらい簡単です:

networks:
  default:
    name: my-app

上記は、あなたがにversion設定していることを前提としています3.5(または、4 +で非推奨になっていない場合は上記)。

他の回答も同じことを指摘しています。これは簡単な要約です。


2

以下をdocker-compose使用して、それらを同時に構成することにより、すべてのコンテナーが同じネットワークに接続されるようにします。

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

これにより、たとえば、フロントの1つのコンテナーから、linkまたはdepends_on1つのAPIのコンテナーを作成できますか?
Jivan 2016年

実際、私があなたが提案したことをすると、docker-composeがどちらかbuild path ~/front/api either does not exist or is not accessibleまたはその逆で返信しますbuild path ~/api/front either does not exist or is not accessible
Jivan

1
同時に作成している場合は、必要ありません。すべてのコンテナーを含むネットワークが作成され、それらはすべて、(コンテナー名ではなく)構成ファイルからのサービス名を介して通信できます。
Nauraushaun

2つの作成ファイルが同じフォルダーにある方が簡単な場合があります。しかし、私はそれが必要だとは思いません-それはどちらの方法でもうまくいくはずだと思います。
Nauraushaun

2
このソリューションは機能しません。このスレッドに関する私のコメントを参照してください:github.com/docker/compose/issues/3530#issuecomment-222490501
johnharris85 '29

2

更新:作成ファイルバージョン3.5以降:

私は同様の問題に遭遇し、私のdocker-compose.ymlプロジェクトの1つに小さな変更を加えることで解決しました。

たとえば、2つのAPI scoringとがありnerます。Scoringapiはner、入力リクエストを処理するために、apiにリクエストを送信する必要があります。そのためには、両方が同じネットワークを共有すると仮定します。

注:すべてのコンテナーには独自のネットワークがあり、Docker内でアプリを実行するときに自動的に作成されます。たとえば、ner apiネットワークはのように作成されner_default、スコアリング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、次のコマンドを使用して呼び出された同じネットワークの一部であることがわかります 。

docker inspect 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": ""
    },
    ...
}

1

.envを含むすべてのプロジェクトにファイルを追加できますCOMPOSE_PROJECT_NAME=somename

COMPOSE_PROJECT_NAMEは、すべてのプロジェクトで使用されるように、リソースの名前に使用される接頭辞を上書きしますsomename_defaultネットワークとしてれるため、サービスが同じプロジェクト内にある場合と同様にサービスが互いに通信できるようにするためです。

注意:他のプロジェクトから作成された「孤立した」コンテナに対して警告が表示されます。


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

0

別のdocker-composeネットワークを使用するには、次のようにします(docker-compose間でネットワークを共有するため)。

  1. 最初のdocker-composeプロジェクトを実行する up -d
  2. 次の方法で、最初のdocker-composeのネットワーク名を見つけます。 docker network ls(ルートディレクトリプロジェクトの名前が含まれています)。
  3. 次に、2番目のdocker-composeファイルで、以下の構造によってこの名前を使用します。

2番目の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

0

別のオプションは、「docker-compose」で最初のモジュールを実行して、モジュールに関連するIPを確認し、2番目のモジュールを外部のような以前のネットに接続し、内部IPをポイントすることです。

例app1-サービス行で作成された新しいネットワーク、下部として外部:trueとマークしますapp2-起動時にapp1によって作成された「新しいネットワーク」を示し、下部として外部:trueとマークし、設定で設定します接続するには、app1がこのネットに持っているIP。

これで、あなたはお互いに話すことができるはずです

*この方法は、過度に複雑な構成を行わないようにするために、ローカルテストに重点を置いています**非常に「パッチ方法」であることがわかっていますが、私にとっては機能します。


0

あなたがいる場合

  • 二つの容器の間で通信しようとする異なるドッキングウィンドウ・コンプロジェクト同じネットワークを使用したくありませんのletのは、彼らが同じポート上でPostgreSQLやRedisのコンテナを持っているでしょうし、あなたがそれを使用するこれらのポートを変更していないではないことを好むだろうと言うので(同じネットワークで)
  • ローカルで開発していて、2つのdocker composeプロジェクト間の通信を模倣したい
  • localhostで2つのdocker-composeプロジェクトを実行する
  • 特にDjangoアプリまたはDjango Rest Framework(drf)APIを開発し、いくつかの公開されたポートでコンテナー内でアプリを実行する
  • Connection refused2つのコンテナー間の通信を試行中に取得

そしてあなたがしたい

  • コンテナが同じ「ドッカーネットワーク」なしで(またはその逆に)api_a通信するapi_b

(以下の例)

2番目のコンテナーの「ホスト」を、Dockerコンテナー内からマップされるコンピューターとポートのIPとして使用できます。このスクリプトでコンピューターの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_aDjangoアプリを実行しているコンテナー内: manage.py runserver 0.0.0.0:8000

そして、他のプロジェクトからの2番目の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_bDjangoアプリを実行しているコンテナー内: manage.py runserver 0.0.0.0:8001

そして、コンテナapi_aからapi_bそのURL に接続しようとしていますapi_bようになります。 http://<get_ip_from_script_above>:8001/

2つ以上(3つ以上)のdocker-composeプロジェクトを使用していて、それらすべてに共通のネットワークを提供することが難しい場合、これは特に価値があります-優れた回避策とソリューションです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.