「ホスト名」を介してDockerコンテナー間で通信する方法


90

モノリシックサーバーを多数の小さなDockerコンテナーに分割する予定ですが、「コンテナー間通信」に適したソリューションはまだ見つかりません。これは私のターゲットシナリオです:

対象シナリオ

コンテナーをリンクする方法とポートを公開する方法は知っていますが、これらのソリューションはどれも満足のいくものではありません。

従来のサーバーネットワークのように、コンテナー間でホスト名(コンテナー名)を介して通信するソリューションはありますか?


私は最近あなたが探していることを正確に行う文書を書きました。基本的には、複数のコンテナー(プロセスごとに1つ)をインストールして統合する方法を文書化しています。「コンテナ間通信」はゲームの一部です
xuhdev

Tumtum Blogを見つけたところ、Dockerの公式ドキュメントでこの段落に遭遇しました。この段落をいつも見逃していたのか、それとも新しく追加されたのかはわかりませんが、それがまさに私が必要とするものです:)
Patrick Gotthard

docker 1.10がリリースされ、docker connectが素晴らしい(github.com/docker/docker/blob/…)。下記の私の編集済みの回答を
VonC

2
docker-composeを試してみてください。非常によく機能します。
Suhas Chikkanna 2017

回答:


27

編集:Docker 1.9以降、docker networkコマンド(下記のhttps://stackoverflow.com/a/35184695/977939を参照 )は、これを実現するための推奨される方法です。


私の解決策は、DNSレコードが自動的に更新されるようにホスト上でdnsmasqをセットアップすることです。「A」レコードにはコンテナの名前があり、コンテナのIPアドレスを自動的にポイントします(10秒ごと)。自動更新スクリプトはここに貼り付けられます。

#!/bin/bash

# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}

# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}

# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}

declare -A service_map

while true
do
    changed=false
    while read line
    do
        name=${line##* }
        ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
        if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
        then
            service_map[$name]=$ip
            # write to file
            echo $name has a new IP Address $ip >&2
            echo "host-record=$name,$ip"  > "${DNSMASQ_CONFIG}/docker-$name"
            changed=true
        fi
    done < <(${DOCKER} ps | ${TAIL} -n +2)

    # a change of IP address occured, restart dnsmasq
    if [ $changed = true ]
    then
        systemctl restart dnsmasq
    fi

    ${SLEEP} $INTERVAL
done

dnsmasqサービスがで利用できることを確認してくださいdocker0。次に、コンテナを起動し--dns HOST_ADDRESSて、このミニDNSサービスを使用します。

リファレンス:http : //docs.blowb.org/setup-host/dnsmasq.html


それは面白そうで、私の--link回答よりもはるかに弾力性があります。+1
VonC、2015年

@VonCは、新しいlibnetworkがこの回避策を置き換える可能性があるようです。見てみましょう。
xuhdev

以下のように@xuhdev Iセットアップのdnsmasq docs.blowb.org/setup-host/dnsmasq.html。しかし、Dockerコンテナーからdigを使用すると問題が発生し、タイムアウトします。しかし、ホストのdocker0インターフェイスへのpingは機能します。また、docker hostから同じdocker0 ipを使用して動作します。何か提案はありますか?
Satheesh 2016

1
@Satheesh多分それはあなたのコンテナがホストからDNSをクエリすることを防ぐのはあなたのファイアウォール設定ですか?
xuhdev 2016

@xuhdevおかげで、問題の原因となった私のホストマシンにファイアウォールが設定されました。firewalldをかがめると、コンテナはホスト上のdnsmasqと通信します
Satheesh

205

新しいネットワーク機能を使用すると、名前でコンテナーに接続できるため、新しいネットワークを作成すると、そのネットワークに接続されているコンテナーは、名前で他のコンテナーに到達できます。例:

1)新しいネットワークを作成する

$ docker network create <network-name>       

2)コンテナーをネットワークに接続する

$ docker run --net=<network-name> ...

または

$ docker network connect <network-name> <container-name>

3)Pingコンテナーを名前で

docker exec -ti <container-name-A> ping <container-name-B> 

64 bytes from c1 (172.18.0.4): icmp_seq=1 ttl=64 time=0.137 ms
64 bytes from c1 (172.18.0.4): icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from c1 (172.18.0.4): icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from c1 (172.18.0.4): icmp_seq=4 ttl=64 time=0.074 ms

ドキュメントのこのセクションを参照してください。

注:レガシーとは異なりlinks、新しいネットワーク環境変数を作成せず、他のコンテナーと環境変数を共有しません。

この機能は現在エイリアスをサポートしていません


4
よく働く。デフォルトのネットワークがデフォルトでこれを有効にしないのはなぜですか?
ステファン

それほど明白ではない部分は、別のコンテナーで実行されているアプリを再起動する必要があることです。では、コンテナAがコンテナBでアプリを実行して再起動するにはどうすればよいでしょうか。明らかに、ある種の通信バスの必要性があるようです。私の心の一番上は、シグナリングとコンテナ間通信にRedisを使用することです。したがって、すべてのコンテナがredisシャネルにサブスクライブし、そこで話し合うことになります... docker-composeで公開されたポートの変更についてはどうですか完全な.ymlファイルが必要docker-compose down,up,restartですか?
固有フィールド

これはまさに私が一日中探していたものです!コンテナ名/ IDでネットワークノードを参照できることを知りませんでした。ありがとうございました!
elliotwesoff

1
@Stéphane bridge下位互換性があるため、デフォルトのネットワークでは無効になっていますが、はい、同意します。デフォルトで必ず有効にする必要があります。
helmesjo 2018年

15

それはする必要があります--linkのためにあるホスト名の部分は、少なくとも、。ドッキングウィンドウ1.10、およびPR 19242、それは次のようになります。

docker network create --net-alias=[]: Add network-scoped alias for the container

(下の最後のセクションを参照)

それがファイル詳細の更新/etc/hostsです

Dockerは、環境変数に加えて、ソースコンテナーのホストエントリを/etc/hostsファイルに追加します。

たとえば、LDAPサーバーを起動します。

docker run -t  --name openldap -d -p 389:389 larrycai/openldap

そして、そのLDAPサーバーをテストするためのイメージを定義します。

FROM ubuntu
RUN apt-get -y install ldap-utils
RUN touch /root/.bash_aliases
RUN echo "alias lds='ldapsearch -H ldap://internalopenldap -LL -b
ou=Users,dc=openstack,dc=org -D cn=admin,dc=openstack,dc=org -w
password'" > /root/.bash_aliases
ENTRYPOINT bash

-linkを使用して、テスト画像内で' openldap'コンテナーを ' internalopenldap' として公開できます。

 docker run -it --rm --name ldp --link openldap:internalopenldap ldaptest

次に、「lds」と入力すると、そのエイリアスが機能します。

ldapsearch -H ldap://internalopenldap ...

それは人々を返すでしょう。画像internalopenldapから意味に正しく達しているldaptest


もちろん、Docker 1.7にはが追加されlibnetwork、コンテナーを接続するためのネイティブなGo実装が提供されます。ブログ投稿をご覧ください。
コンテナネットワークモデル(CNM)により、より完全なアーキテクチャが導入されました

https://blog.docker.com/media/2015/04/cnm-model.jpg

これにより、新しい「ネットワーク」コマンドでDocker CLIが更新-netされ、「」フラグを使用してコンテナーをネットワークに割り当てる方法が文書化されます。


docker 1.10には新しいセクションNetwork-scoped aliasがあり、現在公式に文書化されていnetwork connectます:

リンクはコンテナー内でローカライズされるプライベートな名前解決を提供しますが、ネットワークスコープのエイリアスは、特定のネットワークのスコープ内の他のコンテナーが別名でコンテナーを検出する方法を提供します。
サービスのコンシューマーによって定義されるリンクエイリアスとは異なり、ネットワークスコープのエイリアスは、サービスをネットワークに提供しているコンテナーによって定義されます。

上記の例を続けて、別のコンテナをisolated_nwネットワークエイリアスで作成します。

$ docker run --net=isolated_nw -itd --name=container6 -alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17

--alias=[]         

コンテナーのネットワークスコープのエイリアスを追加する

--linkオプションを使用して、別のコンテナを優先エイリアスにリンクできます

ネットワークに接続されているコンテナを一時停止、再起動、停止できます。一時停止されたコンテナは接続されたままで、ネットワーク検査で明らかにすることができます。コンテナが停止すると、再起動するまでネットワークに表示されません。

指定した場合、停止したコンテナが再起動すると、コンテナのIPアドレスが再適用されます。IPアドレスが利用できなくなった場合、コンテナは起動に失敗します。

IPアドレスが使用可能であることを保証する1つの方法は--ip-range、ネットワークの作成時にを指定し、その範囲外から静的IPアドレスを選択することです。これにより、このコンテナがネットワーク上にないときに、IPアドレスが別のコンテナに割り当てられないことが保証されます。

$ docker network create --subnet 172.20.0.0/16 --ip-range 172.20.240.0/20 multi-host-network

$ docker network connect --ip 172.20.128.2 multi-host-network container2
$ docker network connect --link container1:c1 multi-host-network container2

3
--linkの問題は、リンクされたコンテナも再起動しないとコンテナを再起動できないことです。私のグラフィックを見ると、MySQLコンテナーを再起動すると、他のコンテナーのカスケードが再起動します。
Patrick Gotthard

3

編集:それはもはや最先端ではありません:http//blog.docker.com/2016/02/docker-1-10/

元の回答
私は一晩中それと戦いました。最先端技術を恐れていない場合は、Dockerエンジンの最新バージョンとDocker composeの両方がlibnetworkを実装しています。

適切な構成ファイル(バージョン2に配置する必要がある)を使用して、すべてが相互に認識されるサービスを作成します。そして、ボーナスとして、それらをdocker-composeでスケーリングすることもできます(ホスト上のポートをバインドしない任意のサービスをスケーリングできます)

ここにサンプルファイルがあります

version: "2"
services:
  router:
    build: services/router/
    ports:
      - "8080:8080"
  auth:
    build: services/auth/
  todo:
    build: services/todo/
  data:
    build: services/data/

そして、この新しいバージョンの構成ファイルの参照:https : //github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md


1

私の知る限り、Dockerだけを使用することはできません。コンテナーip:sをホスト名にマップするには、DNSが必要です。

すぐに使えるソリューションが必要な場合。1つの解決策は、たとえばKontenaを使用することです。Weaveのネットワークオーバーレイテクノロジーが付属しており、このテクノロジーを使用して各サービスの仮想プライベートLANネットワークを作成し、すべてのサービスにからアクセスできますservice_name.kontena.local-address

Wordpressサービスがwordpress-mysql.kontena.localアドレスを使用してMySQLサーバーに接続するWordpressアプリケーションのYAMLファイルの簡単な例を次に示します。

wordpress:                                                                         
  image: wordpress:4.1                                                             
  stateful: true                                                                   
  ports:                                                                           
    - 80:80                                                                      
  links:                                                                           
    - mysql:wordpress-mysql                                                        
  environment:                                                                     
    - WORDPRESS_DB_HOST=wordpress-mysql.kontena.local                              
    - WORDPRESS_DB_PASSWORD=secret                                                 
mysql:                                                                             
  image: mariadb:5.5                                                               
  stateful: true                                                                   
  environment:                                                                     
    - MYSQL_ROOT_PASSWORD=secret
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.