次のように実行されているDockerコンテナーがいくつかあります。
NginxはWebアプリ1および2内のWebアプリケーションサーバーに接続する必要があり、WebアプリはPostgreSQLと通信する必要があるため、次のようなリンクがあります。
これは最初はかなりうまくいきます。ただし、Webアプリ1とWebアプリ2の新しいバージョンを開発するときは、それらを置き換える必要があります。私がしていることは、Webアプリコンテナを削除し、新しいコンテナをセットアップして起動することです。
Webアプリコンテナーの場合、最初のIPアドレスは次のようになります。
そして、それらを交換すると、新しいIPアドレスが追加されます。
現在、Nginxコンテナで公開されている環境変数は、まだ古いIPアドレスを指し示しています。ここに問題があります。コンテナ間のリンクを壊さずにコンテナを交換するにはどうすればよいですか?同じ問題がPostgreSQLでも発生します。 PostgreSQLイメージバージョンをアップグレードする場合は、必ず削除して新しいバージョンを実行する必要がありますが、コンテナーグラフ全体を再構築する必要があるため、これは実際のサーバー操作には理想的ではありません。
--link
の効果は静的であるため、シナリオでは機能しません(現在、再リンクはありませんが、 リンクの削除 が可能です)。
Dockerize.itで2つの異なるアプローチを使用して、リンクまたはアンバサダーなしでこれを解決しています(ただし、アンバサダーを追加することもできます)。
1)ダイナミックDNSを使用
一般的な考え方は、データベース(またはその他のサービス)に単一の名前を指定し、コンテナを開始および停止するときに、短命のDNSサーバーを実際のIPで更新することです。
SkyDock から始めました。 DNSサーバーと、自動的に更新されるモニターの2つのdockerコンテナーで動作します。後で、 Consul を使用してよりカスタムなものに移動しました(また、dockerizedバージョンを使用: docker-consul )。
これを進化させたのは(まだ試していませんが)etcdなどをセットアップし、そのカスタムAPIを使用してIPとポートを学習することです。ソフトウェアは動的再構成もサポートする必要があります。
2)docker bridge ipを使用します
コンテナポートを公開するときは、よく知られたアドレスを持つ(または持つことができる)docker0
ブリッジにそれらをバインドするだけです。
コンテナを新しいバージョンに置き換える場合、新しいコンテナが同じIPで同じポートを公開するようにします。
これは簡単ですが、より制限されています。同様のソフトウェア(たとえば、2つのコンテナがdocker0
ブリッジの3306ポートでリッスンできない)などを実行すると、ポートの競合が発生する可能性があります。したがって、現在のお気に入りはオプション1です。
リンクは特定のコンテナ用であり、コンテナの名前に基づいていません。したがって、コンテナを削除すると、リンクは切断され、新しいコンテナは(同じ名前であっても)自動的に置き換わりません。
新しいネットワーク機能を使用すると、名前でコンテナに接続できるため、新しいネットワークを作成すると、そのネットワークに接続されているコンテナは名前で他のコンテナにアクセスできます。例:
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
とは異なり、新しいネットワークはそうではありません環境変数を作成し、環境変数を他のコンテナと共有しません。
現在、この機能はエイリアスをサポートしていません
ambassador container を使用できます。ただし、上記と同じ問題が発生するため、アンバサダーコンテナをクライアントにリンクしないでください。代わりに、Dockerホストのアンバサダーコンテナの公開ポート(通常は172.17.42.1)を使用します。例:
postgresボリューム:
$ docker run --name PGDATA -v /data/pgdata/data:/data -v /data/pgdata/log:/var/log/postgresql phusion/baseimage:0.9.10 true
postgresコンテナー:
$ docker run -d --name postgres --volumes-from PGDATA -e USER=postgres -e PASS='postgres' paintedfox/postgresql
postgresの大使コンテナ:
$ docker run -d --name pg_ambassador --link postgres:postgres -p 5432:5432 ctlc/ambassador
これで、アンバサダーコンテナをリンクせずにpostgresqlクライアントコンテナを起動し、ゲートウェイホスト(通常は172.17.42.1)でpostgresqlにアクセスできます。
$ docker run --rm -t -i paintedfox/postgresql /bin/bash
root@b94251eac8be:/# PGHOST=$(netstat -nr | grep '^0\.0\.0\.0 ' | awk '{print $2}')
root@b94251eac8be:/# echo $PGHOST
172.17.42.1
root@b94251eac8be:/#
root@b94251eac8be:/# psql -h $PGHOST --user postgres
Password for user postgres:
psql (9.3.4)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
postgres=#
postgres=# select 6*7 as answer;
answer
--------
42
(1 row)
bpostgres=#
これで、クライアントを再起動せずに、アンバサダーコンテナを再起動できます。
これは3週間前のdockerの実験的ビルドに含まれており、サービスが導入されています。 https://github.com/docker/docker/blob/master/experimental/networking.md
Dockerコンテナを--publish-service <name>
引数。この名前はDNS経由でアクセスできます。これは、コンテナの再起動時に持続します(もちろん、同じサービス名でコンテナを再起動する限り)
まだ興味があれば、各dockerコンテナの/ etc/hostsファイルのHostエントリを使用する必要があります。ENV変数は自動的に更新されないため、ENV変数に依存しないでください。
リンクされたコンテナごとに、LINKEDCONTAINERNAME_PORT_PORTNUMBER_TCPなどの形式でホストファイルエントリがあります。
以下はdockerからのものです docs
Docker環境変数に関する重要な注意事項
/ etc/hostsファイルのホストエントリとは異なり、環境変数に保存されているIPアドレスは、ソースコンテナが再起動されても自動的に更新されません。/etc/hostsのホストエントリを使用して、リンクされたコンテナのIPアドレスを解決することをお勧めします。
これらの環境変数は、コンテナ内の最初のプロセスに対してのみ設定されます。 sshdなどの一部のデーモンは、接続用のシェルを生成するときにそれらをスクラブします。
また、リンクをそのまま保持するために中間コンテナを使用するアンバサダーメソッドを試すこともできます...(詳細は https://docs.docker.com/articles/ambassador_pattern_linking/ を参照)
openSVCアプローチでは、次の方法で回避できます。
コンテナを交換するたびに、確実に正しいIPアドレスに接続します。
チュートリアルはこちら=> OpenSVCを使用したDocker Multi Containers
tutoの最後にある「複雑なオーケストレーション」の部分をお見逃しなく。これは、コンテナを正しい順序で開始/停止するのに役立ちます(postgresqlサブセット1つ+ webappサブセット1つ+ nginxサブセット1つ)
主な欠点は、webappおよびPostgreSQLポートをパブリックアドレスに公開することです。実際には、パブリックで公開する必要があるのはnginx tcpポートのみです。
これを解決するには、名前に dockerlinks を使用できます。
最も基本的なセットアップは、最初にnamedデータベースコンテナを作成することです:
$ Sudo docker run -d --name db training/postgres
次に、dbに接続するWebコンテナを作成します。
$ Sudo docker run -d -P --name web --link db:db training/webapp python app.py
これにより、コンテナをIPアドレスと手動で接続する必要がなくなります。
イメージの接続ポートをホストの固定ポートにバインドし、代わりにそれらを使用するようにサービスを構成できます。
これには欠点もありますが、あなたの場合にはうまくいくかもしれません。
ネットワークスコープのエイリアス は、この場合に必要なものです。これはかなり新しい機能です。1つのコンテナからのみアクセス可能なリンクエイリアスとは異なり、ネットワーク全体にサービスを提供するコンテナを「公開」するために使用できます。
コンテナ間にいかなる種類の依存関係も追加しません。再起動、交換、起動順序に関係なく、両方が実行されている限り通信できます。/etc/hostsではなく、内部的にDNSを使用していると思います
docker run --net=some_user_definied_nw --net-alias postgres ...
のように使用すると、同じネットワーク上の任意のコンテナからそのエイリアスを使用して接続できます。
デフォルトのネットワークでは動作しません。残念ながら、すべてのコンテナに対してdocker network create <network>
で作成し、--net=<network>
で使用する必要があります( composeサポートも同様 )。
コンテナがダウンしているためエイリアスが到達できないことに加えて、複数のコンテナはエイリアスを共有することもできます。この場合、正しいコンテナに解決されることは保証されません。しかし、場合によってはシームレスなアップグレードに役立つ可能性があります。
現時点ではまだ十分に文書化されておらず、manページを読むだけでは理解するのが困難です。
別の方法は、--net container:$CONTAINER_ID
オプションを使用することです。
docker run --name db_net ubuntu:14.04 sleep infinity
docker run --name app1_net --link db_net:db ubuntu:14.04 sleep infinity
docker run --name app2_net --link db_net:db ubuntu:14.04 sleep infinity
docker run -p 80 -p 443 --name nginx_net --link app1_net:app1 --link app2_net:app2 ubuntu:14.04 sleep infinity
docker run --name db --net container:db_net pgsql
docker run --name app1 --net container:app1_net app1
docker run --name app2 --net container:app1_net app2
docker run --name nginx --net container:app1_net nginx
「ネットワーク」コンテナに触れない限り、リンクのIPアドレスは変更されません。