コンテナの 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.confsearch 行で書かれているものです。コンテナのプロセスがホスト名 host に接続しようとするとき、 search ドメインに example.com が指定されていれば、DNS 機構は host だけでなく、 host.example.com に対しても名前解決を行います。検索用ドメインを指定したくない場合は、 --dns-search=. を使います。
  • --dns-opt=オプション :コンテナ内の /etc/resolv.confoptions 行で 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 以降に作成されたコンテナのみ、上記の自動更新機能が使えます。