Dockerのネットワークの基礎
今までいろいろ触ってきて,Dockerネットワーク周りに関しては何となくは理解していたが,人に説明できるほど理解してなかったのでまとめておく.基本は,Advanced networking - Docker Documentationがベースになっている.
仮想ブリッジの仕組み
Dockerのネットワークは,仮想ブリッジdocker0を通じて管理され,他のネットワークとは隔離された環境で動作する.
Dockerデーモンを起動すると,
- 仮想ブリッジ
docker0の作成 - ホストの既存ルートからの空きのIPアドレス空間を検索
- 空きから特定の範囲のIPアドレス空間を取得
- 取得したIPアドレス空間を
docker0に割り当て
が行われる.
コンテナを起動すると,コンテナには以下が割り当てられる.
docker0に紐づいたveth(Virtual Ethernet)インターフェースdocker0に割り当てられたIPアドレス空間から専用のIPアドレス
そしてdocker0はコンテナのデフォルトのgatewayとして利用されるようになる.コンテナに付与されるvethは仮想NICで,コンテナ側からはeth0として見える.2つはチューブのように接続され,あらゆるやりとりはここを経由して行われるようになる.
実際にコンテナを起動して確認する.まず,インターフェースから.
1 2 3 | |
1 2 | |
1 2 | |
1 2 3 | |
b9ffb0800ca5コンテナにはveth29c1が,4c0d9b786e8fコンテナにはveth9eb7がそれぞれ割り当てられているのがわかる.
次にIPを見てみる.
1 2 3 | |
1 2 | |
1 2 | |
docker0に割り当てられた172.17.42.1/16のうち,b9ffb0800ca5コンテナには172.17.02が,4c0d9b786e8fコンテナには172.17.0.3がそれぞれ割り当てられているのがわかる.
コンテナ同士のやりとり
コンテナ間のやりとりの制御は,Dockerデーモンの-iccパラメータにより行う.Dockerはこれにiptablesを使っている.
-icc=trueとすると,コンテナ間のやりとりが可能になる(default)-icc=falseとすると,コンテナ同士は隔離される
さらに,コンテナ同士でやりとりするにはportをdocker0に晒す必要がある.これには,以下の2つの方法がある.
- Dockerfileに
EXPOSE <port>を記述する - コンテナ起動時に
--expose <port>を指定する
具体的に,docker0を通じてコンテナ同士を接続する場合は,link機能を使う.コンテナを起動する際に,--link コンテナ名:エイリアス名とすると,環境変数を通じて接続したいコンテナのIPやPortを取得できるようになる(詳しくは,“Dockerコンテナ間のlink,database.ymlの書き方”に書いた).
外部ネットワークからコンテナへのアクセス
外部ネットワークからコンテナにアクセスするには,コンテナを起動するときに外部ポートをdocker0に晒した内部portにマップする必要がある.
例えば,ホストの8080ポートをコンテナの80ポートにマップしてApacheコンテナを起動してみる.
1 2 | |
マッピングは以下で確認できる.
1 2 3 | |
IDと晒したportを基に確認することもできる.
1 2 | |
実際に接続してみる.
1 2 | |
ホスト側のIPの指定を省略することもできる.この場合,自動でポートが選ばれる.
1 2 3 4 5 | |