コンテナの DNS を設定¶
このセクションでは Docker のデフォルト・ブリッジ内でコンテナの DNS を設定する方法を紹介します。ここでの bridge
という名称の bridge
ネットワークは、Docker インストール時に自動的に作成されるものです。
注釈
Docker ネットワーク機能 を使えば、デフォルト・ブリッジ・ネットワークに加え、自分でユーザ定義ネットワークも作成できます。ユーザ定義ネットワーク上で DNS 設定を行う詳細な情報は、 Docker 内蔵 DNS をご覧ください。
Docker が各コンテナにホスト名や DNS 設定を渡すのに、カスタム・イメージを使わず、コンテナ内にホスト名を書くにはどうしたらよいでしょうか。コンテナ内では、 /etc
以下にある3つの重要なファイルを、仮想ファイルを使って新しい情報に上書きする手法を使います。これは実行中のコンテナ内で mount
コマンドを実行すると分かります。
$$ mount
...
/dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ...
/dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ...
/dev/disk/by-uuid/1fec...ebdf on /etc/resolv.conf type ext4 ...
...
この処理により、Docker は resolv.conf
を巧妙に最新版を維持します。この情報はホストマシンが新しい設定を DHCP 経由で受信すると、全てのコンテナに対して反映します。Docker がコンテナの中でこれらのファイルをどう管理するのか正確な情報を持っているので、Docker のバージョンを更新しても変わりません。そのため、ファイルの内容に対して変更を加えるのではなく、以下のオプションを使います。
コンテナのドメイン名サービスに影響を与える4つのオプションがあります。
-h ホスト名
か--hostname=ホスト名
:コンテナ自身が知るホスト名を設定します。これは/etc/hostname
に書かれ、/etc/hosts
にはコンテナ内のホスト IP アドレスが書かれ、その名前がコンテナ内の/bin/bash
プロンプトで表示されます。しかし、ホスト名をコンテナの外から確認するのは大変です。docker ps
でも見えませんし、他のコンテナの/etc/hosts
からも見えません。
--link=コンテナ名
かID:エイリアス
:run
(実行)しているコンテナに対して、新しいコンテナの/etc/hosts
にエイリアス
という名称のエントリを追加します。コンテナを識別する IP アドレスが指し示すのは、コンテナ名か ID
です。これにより、新しいコンテナ内のプロセスは、IP アドレスを知らなくても、ホスト名のエイリアス
を使って接続できます。--link
オプションの詳細については、以降で扱います。Docker は異なる IP アドレスが割り当てられる可能性があり、リンクされたコンテナを再起動すると、Docker は対象となるコンテナの/etc/hosts
のエイリアス
エントリを更新します。
--dns=IPアドレス...
:コンテナの/etc/resolv.conf
ファイルのserver
行に IP アドレスを追加します。コンテナ内のプロセスは、/etc/host
を突き合わせて一致するホスト名が存在しなければ、ここで指定した IP アドレスのポート 53 を名前解決用に使います。
--dns-search=ドメイン名...
: コンテナ内でホスト名だけが単体で用いられた時、ここで指定したドメイン名に対する名前解決を行います。これはコンテナ内の/etc/resolv.conf
のsearch
行で書かれているものです。コンテナのプロセスがホスト名host
に接続しようとするとき、 search ドメインにexample.com
が指定されていれば、DNS 機構はhost
だけでなく、host.example.com
に対しても名前解決を行います。検索用ドメインを指定したくない場合は、--dns-search=.
を使います。
--dns-opt=オプション
:コンテナ内の/etc/resolv.conf
のoptions
行で DNS 解決のオプションを指定します。利用可能なオプションについては、resolv.conf
のオプションをご覧ください。
DNS 設定に関して、オプション --dns=IPアドレス...
、 --dns-search=ドメイン名...
、 --dns-opt=オプション...
の指定がなければ、Docker は各コンテナの /etc/resolv.conf
をホストマシン上( docker
デーモンが動作中 )の /etc/resolv.conf
のように作成します。コンテナの /etc/resolv.conf
の作成時、デーモンはホスト側のオリジナル・ファイルに書かれている nameserver
のエントリを、フィルタリングして書き出します。
フィルタリングが必要になるのは、ホスト上の全てのローカルアドレスがコンテナのネットワークから到達できない場合があるからです。フィルタリングにより、コンテナ内の /etc/resolv.conf
ファイルに nameserver
のエントリが残っていなければ、デーモンはパブリック Google DNS ネームサーバ(8.8.8.8 と 8.8.4.4)をコンテナの DNS 設定に用います。もしデーモン上で IPv6 を有効にしているのであれば、パブリック IPv6 Google DNS ネームサーバを割り当てます(2001:4860:4860::8888 と 2001:4860:4860::8844)。
注釈
ホスト側のローカルなリゾルバにアクセスする必要があるなら、コンテナ内から到達可能になるように、ホスト上にある DNS サービスがローカルホスト以外をリッスンするよう設定が必要です。
ホストマシン側の /etc/resolv.conf
を変更すると何が起こるか気になるでしょう。 docker
デーモンはホスト側の DNS 設定に対する変更を監視しているので、ファイルの変更を通知します。
注釈
ファイル変更の通知は Linux カーネルの inotify 機能に依存しています。現時点では overlay ファイルシステム・ドライバとは互換性がありません。そのため Docker デーモンが「overlay」を使う場合は、 /etc/resolv.conf
の自動更新機能を使えません。
host ファイルが変更されるとき、 resolv.conf
を持っている全てのコンテナ上で、 host ファイルは直ちに最新の host 設定に更新されます。host 設定変更時にコンテナが実行中であれば、コンテナを停止・再起動して反映する必要があります。コンテナ実行中は、 resolv.conf
の内容はそのまま維持されるためです。もし、コンテナがデフォルトの設定で開始される前に resolv.conf
を編集している場合は、ファイルをコンテナ内で編集した内容はそのままで、置き換えられることはありません。もしオプション( --dns
、 --dns-search
、 --dns-port
)がデフォルトのホスト設定に用いられている場合は、同様にホスト側の /etc/resolv.conf
を更新しません。
注釈
/etc/resolv.conf
の更新機能が実装されているのは、Docker 1.5.0 以降に作られたコンテナです。つまり、以前のコンテナはホスト側の resolv.conf
の変更が発生しても検出できません。Docker 1.5 以降に作成されたコンテナのみ、上記の自動更新機能が使えます。
参考
- Configure container DNS
- https://docs.docker.com/engine/userguide/networking/default_network/configure-dns/