コンテナの連結と操作 - Docker User Guide


# コンテナのリンク（連結）と操作

Linking containers together - Docker Documentation
http://docs.docker.com/userguide/dockerlinks/

[Using Docker section](http://docs.docker.com/userguide/usingdocker) において、私たちはネットワークを通して Docker コンテナの中で実行されているサービスにつながる事に触れてきました。これは、Docker コンテナの中で、サービスと動作中のアプリケーションを相互に作用することが出来る方法の１つです。このセクションでは、リンクしている（連結している）コンテナに概念を導入するだけでなく、ネットワーク・ポートを通して、Docker コンテナへの接続をリフレッシュさせる方法を扱います。

## ネットワークポート割り当てのリフレッシャー

[Using Docker section](http://docs.docker.com/userguide/usingdocker) において、私たちは Python Flask アプリケーションのコンテナを作る事ができました。

```
$ sudo docker run -d -P training/webapp python app.py
```

注：コンテナに内部ネットワークと IP アドレスが有る場合（[Using Docker](http://docs.docker.com/userguide/usingdocker/) セクションにおいて、私たちは`docker inspect`コマンドを使って、コンテナの IP アドレスを表示することが出来たのを思い出してください）。Docker は様々なネットワーク設定を持ちます。Docker のネットワークの詳細については、[こちら] (http://docs.docker.com/articles/networking/) を参照してください。

コンテナを `-P` フラグを使い起動すると、自動的に Docker ホストのネットワーク側のポートを、コンテナ内部のランダムな high port の範囲 49000 ～ 49900 に割り当てます。そして、私たちが `docker ps` を実行すると、ポート 5000 が、ポート 49155 に割り当てられていたのを見てきました。

```
$ sudo docker ps nostalgic_morse
CONTAINER ID  IMAGE                   COMMAND       CREATED        STATUS        PORTS                    NAMES
bc533791f3f5  training/webapp:latest  python app.py 5 seconds ago  Up 2 seconds  0.0.0.0:49155->5000/tcp  nostalgic_morse
```

私たちは、コンテナの特定のポートに割り当てるために `-p` フラグを付けるのも見て来ました。

```
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
```

それから、特定のポートを指定するのが何故良くない方法なのか（１つのコンテナしか使えないので）についても見て来ました。

`-p` フラグを使って設定するほかにも、いくつかの方法があります。デフォルトの `-p` フラグは、ホストマシン上で指定されたポートを、すべてのインターフェースに結びつけます。しかし、私たちは特定のインターフェースを指定することも出来ます、たとえば `localhost` のように。

```
$ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
```

これは、ホストマシン上のインターフェース `localhost` か `127.0.0.1` 上のポート 5000 を、コンテナ内部のポート 5000 に結びつけます。

あるいは、コンテナが使うポート 5000 を、`localhost` とだけ指定しても、動的にポートを割り当てられることを見て来ました。

```
$ sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py
```

また `/udp` を末尾に追加することで、UDP ポートに結びつけることができます、たとえば：

```
$ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
```

また、`docker port` ショートカットによって現在のポート割り当て状況を見るのが便利であり、これはまた特定のポートの設定状態を見るのにも便利です。例えば、コンテナのポートをホストマシンの localhost に結びつけると、`docker port` からの出力は次のようになります。

```
$ docker port nostalgic_morse 5000
127.0.0.1:49155
```

メモ：`-p` フラグは、複数のポートを設定するために、複数回使用することができます。

## Docker コンテナのリンク

Docker コンテナは自分自身や他に接続することが出来ず、ネットワークポートマッピングを使うのが唯一の方法です。Docker linking は、親のコンテナが選択した子どもの情報を見ることが出来る、親子関係を作ります。

## コンテナのネーミング

Docker の連結（リンク）を行うには、名付けるコンテナ名に依存します。私たちは既に、私たちが作成したコンテナには自動的に名前が付けられますが、実際には、ガイドで見慣れてきた `nostalgic_morse` のように、古い友達のようなものです。また、自分自身でコンテナに名付けることが出来ます。名前をつけることは、２つの役立つ機能を提供します。

1. コンテナに名前を付けることは、自分がコンテナの名前を覚えやすくするために多少は便利です。たとえば、ウェブアプリケーションが動作するコンテナを `web` と名付けます。

2. Docker が提供するのは、他のコンテナからの参照ポイントを提供します。例えば、`web` というコンテナを `db` というコンテナにリンクするとします。

自分でコンテナ名を `--name` フラグを使って名付けられます。たとえば

```
$ sudo docker run -d -P --name web training/webapp python app.py
```

新しく起動するコンテナに対し、`--name` フラグを使って 'web' と呼ばれる名前を付けてます。コンテナの名前は `docker ps` コマンドを使って見る事が出来ます。

```
$ sudo docker ps -l
CONTAINER ID  IMAGE                  COMMAND        CREATED       STATUS       PORTS                    NAMES
aed84ee21bde  training/webapp:latest python app.py  12 hours ago  Up 2 seconds 0.0.0.0:49154->5000/tcp  web
```

また `docker inspect` を使う事で、コンテナ名を返すことも出来ます。

```
$ sudo docker inspect -f "{{ .Name }}" aed84ee21bde
/web
```

注：コンテナ名はユニークでなくてはいけません。この意味するところは、`web` と呼べるコンテナは１つだけということです。もし、コンテナ名を他でも再利用したい場合は、新しいコンテナを同じ名前で作る前に、古いコンテナを `docker rm` コマンドで消す必要があります。他の方法としては、`docker run` コマンドに `--rm` フラグを使う方法があります。これは、それが止まったら、直ぐにコンテナが削除されます。

## コンテナの連結

発見したコンテナに対してリンクすることで、お互い安全に通信することができます。リンクを作成するには `--link` フラグを使います。新しくコンテナを作りましょう、コンテナはデータベースです。

```
$ sudo docker run -d --name db training/postgres
```

ここで `training/postgres` イメージ、中には PostgreSQL データベースを含まれるものを使って、`db` という新しいコンテナを作成しました。

それでは、新しい `web` コンテナを作成し、それを私たちの `db` コンテナにリンクしましょう。

```
$ sudo docker run -d -P --name web --link db:db training/webapp python app.py
```

これは新しい `web` コンテナを既に作成した `db` コンテナにリンクします。`--link` フラグは次のようになります。

```
--link name:alias
      名前　エイリアス
```

ここでの `name` は、リンク使用としているコンテナ名であり、`alias` はリンク名に対する別名です。それでは、エイリアスがどのように使われているかを見ていきましょう。

リンク済みのコンテナは `docker ps` によって見る事が出来ます。

```
$ docker ps
CONTAINER ID  IMAGE                     COMMAND               CREATED             STATUS             PORTS                    NAMES
349169744e49  training/postgres:latest  su postgres -c '/usr  About a minute ago  Up About a minute  5432/tcp                 db
aed84ee21bde  training/webapp:latest    python app.py         16 hours ago        Up 2 minutes       0.0.0.0:49154->5000/tcp  db/web,web
```

`NAMES` 列には、`db` と `web` という名前のコンテナが見えますが、`web` のコンテナには `db/web` も見えます。これは `web` コンテナは `db` コンテナからリンクされ、親子関係があることがわかります。

それでは、コンテナにリンクするというのは、何をしているのでしょうか。これまで２つのコンテナ間でリンクを作成するときに、親子関係が発生する事がわかりました。親コンテナ、ここでは `db` が子コンテナである `web` に関する情報にアクセスすることができます。このようにすることで、Docker はコンテナ上に外部のポートを露出させることなく、コンテナ間に安全なトンネルをつくることができます。`db` コンテナを起動するとき、`-P` や `-p` フラグを使わなかったことに注意しておいてください。コンテナがリンクされることによって、PostgreSQL データベースをネットワーク上に晒す必要はありません。

Docker では、親コンテナが子コンテナの情報に関する情報に触れるためには、２つの情報があります。

* 環境変数
* /etc/hosts ファイルの更新

まずはじめに、Docker がセットする環境変数を見てみましょう。コンテナの環境変数を見るために、`env` コマンドを使ってみましょう。

```
$ sudo docker run --rm --name web2 --link db:db training/webapp env
. . .
DB_NAME=/web2/db
DB_PORT=tcp://172.17.0.5:5432
DB_PORT_5000_TCP=tcp://172.17.0.5:5432
DB_PORT_5000_TCP_PROTO=tcp
DB_PORT_5000_TCP_PORT=5432
DB_PORT_5000_TCP_ADDR=172.17.0.5
. . .
```

注：これらの環境変数がセットされるのは、コンテナの起動時だけです。同様に、何らかのデーモン ( `sshd` など ) は、生成されたシェル ( spawning shell ) に接続するときには無効にされます。

これまで `db` コンテナに関する情報を、Docker が生成したいくつかの環境変数を使って知ることができました。
各々の環境変数は `DB_` という接頭辞がついており、これは先ほど設定した `alias` から作成されるものです。
もし `alias` が `db1` であれば、変数による接頭辞は `DB1_` となるでしょう。`db` コンテナ上のデータベースに対して接続しているアプリケーションの設定を行いたい時、これら環境変数を使用することが出来ます。
ここの接続は安全でプライベートなものになり、リンクされた `web` コンテナのみが `db` コンテナに接続する事ができます。

加えて、Docker の環境変数のホスト情報から、`/etc/hosts` に、親情報のエントリを追加します。それでは `web` コンテナ内からファイルをみてみましょう。

```
root@aed84ee21bde:/opt/webapp# cat /etc/hosts
172.17.0.7  aed84ee21bde
. . .
172.17.0.5  db
```

私たちはエントリされているホストに関する２つのエントリを見ることが出来ます。1つめは、`web` コンテナが、ホスト名にコンテナ ID を使用出来るようにするためです。２つめは、`db` コンテナの IP アドレスを、エイリアス（別名）として使えるようにするためです。それでは、このホスト名をつかって ping を試みましょう。

```
root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping
root@aed84ee21bde:/opt/webapp# ping db
PING db (172.17.0.5): 48 data bytes
56 bytes from 172.17.0.5: icmp_seq=0 ttl=64 time=0.267 ms
56 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.250 ms
56 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.256 ms
```

注：コンテナの中には `ping` がないので インストールする必要があります。

`ping` コマンドを `db` コンテナに対して行うために、`127.17.0.5` の名前解決を行うホストエントリを用いています。私たちは、このホストエントリを使って、アプリケーションが `db` コンテナに接続させるために使う事ができます。

注：１つの親に複数の子コンテナをリンクすることが出来ます。たとえば、複数の web コンテナ群を `db` コンテナに対して接続する事もできるのです。

## 次のステップ

これでどのように Docker コンテナに対してリンクするかが分かりましたので、次のステップは、どのようにコンテナ内のデータやボリュームやマウントするかを学びます。

Go to [Managind Data in Containers](http://docs.docker.com/userguide/dockervolumes).