web-dev-qa-db-ja.com

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

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

Target scenario

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

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

72

編集: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サービスを使用するには、--dns Host_ADDRESSでコンテナーを起動します。

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

25
xuhdev

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

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

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

注:従来のlinksとは異なり、新しいネットワークは環境変数を作成しません、環境変数を他のコンテナと共有することもできません。

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

173
Hemerson Varela

少なくともホスト名の部分については、 --linkの目的は であるべきです。
docker 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実装を提供します。 ブログ投稿 を参照してください。
Container Network Model(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
12
VonC

EDIT:もうEdgeから出血していません: http://blog.docker.com/2016/02/docker-1 -10 /

元の回答
一晩中戦いました。 Edgeのブリーディングを恐れないのであれば、最新バージョンの Docker engineDocker compose は両方ともlibnetworkを実装しています。

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

以下に例を示します file

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

3
Dolanor

私の知る限り、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
1
Lauri

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

0