Docker Network - Container DNS
Default bridge network
どのようにして Docker はそれぞれのコンテナに対して hostname や DNS の設定を与えているか。(カスタムイメージで内部的に書き換えるなどを行わずに)
これは、書き換え可能なコンテナ内の 3 つの重要な /etc (仮想)ファイルにて実現される。
コンテナ内で mount を実行したときに見ることができる。
root@f38c87f2a42d:/# 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 ...
...
これにより、ホストが DHCP から新しい設定を受け取ったときにすぐにすべてのコンテナに対して変更を適用できる。
Docker がこれらのファイルを実際にどのように扱っているかは、新バージョンになると変わってしまう可能性があるので、ファイルについてはそれらに任せておき、代わりに以下の Docker オプションを使うと良いだろう。
-h HOSTNAME or --hostname=HOSTNAME
hostname をコンテナに設定する。
これは /etc/hostname および /etc/host にコンテナの host-facing IP の名前を書き込み、またコンテナ内部の /bin/bash にて表示されるプロンプトとして利用される。
しかし、 hostname をコンテナ外部から参照するのは難しい。 docker ps や他のコンテナの /etc/hosts ファイルからも確認できない。
--link=CONTAINER_NAME or ID:ALIAS
新しいコンテナの /etc/hosts に追加の ALIAS (CONTAINER_NAME_or_ID から参照可能なコンテナの IP アドレスを指すもの) を与える。
これは新しいコンテナ内のプロセスに対して、 IP アドレスを知る必要なく hostname の ALIAS で接続可能にする。
Docker はコンテナの restart 時に異なる IP を与える可能性があるので、 /etc/hosts の ALIAS エントリを書き換える。
--dns=IP_ADDRESS...
コンテナ内の /etc/resolv.conf の nameserver 行に IP アドレスを追加する。
コンテナ内のプロセスは、 /etc/hosts に名前がないときにこの IP アドレスの 53 番ポートを利用して名前解決を試みる。
--dns-search=DOMAIN...
コンテナ内の /etc/resolv.conf の search 行にドメイン名を追加する。
挙動は通常の Linux の /etc/resolv.conf と一緒。
ここ に全部書いてある。
--dns-opt=OPTION...
コンテナ内の /etc/resolv.conf の options 行にオプションを追加する。
挙動は通常の Linux の /etc/resolv.conf と一緒。
ここ に全部書いてある。
Docker コンテナ内の /etc/resolv.conf ファイルは、ホストの /etc/resolv.conf のように見える。
コンテナの /etc/resolv.conf が生成されるとき、 Docker デーモンはホストのもとのファイルの nameserver 行から localhost IP をフィルタリングする。
コンテナネットワークからみてすべての localhost アドレスは unreachable なので、フィルタリングの必要がある。
フィルタリング後、 nameserver がない場合は、 public Google DNS nameservers (8.8.8.8 and 8.8.4.4) を追加する。
ホスト側の /etc/resolv.conf を変更した場合だが、 Docker デーモンはファイルの変更を検知する仕組みを持っているので、 ホスト側の DNS の変更を監視している。
※ このファイル変更検知の仕組み (file change notifier) は、 Linux カーネルの inotify 機能を利用している。この機能は現在 overlay filesystem driver と互換性がないので、 "overlay" を利用する Docker デーモンでは /etc/resolv.conf の自動更新は利用できない。
ホスト側のファイルが更新されると、ホスト側と一致する resolv.conf を持っている停止中のコンテナについては、すぐに更新が適用される。
稼働中のコンテナについては、 stop/start が必要となる。(to ensure atomic writes)
コンテナ起動後に書き換えられた resolv.conf については、変更は実施されない。
オプション (--dns, --dns-search, or --dns-opt) で書き換えた場合も同様。
Embedded DNS server in user-defined networks
Docker daemon は name, net-alias, aliased by link などによりビルトインで service discovery を提供するような embedded DNS server を実装している。
例によって、これもバージョンアップと共に実装は大きく変わる可能性がある。
上のものと似ているが、以下にオプションを紹介する。
--name=CONTAINER-NAME
--name を利用して設定されたコンテナ名は、 user-defined docker network から discover するために使われる。
embedded DNS server はコンテナ名と IP アドレスのマッピングを管理する。
--network-alias=ALIAS
user-defined network 内のコンテナは、上の --name に加え、 1 つ以上の --network-alias (or --alias in docker network connect command) からも discover される。
embedded DNS server は、固有の user-defined network におけるすべてのコンテナの alias と IP アドレスのマッピングを管理する。
1 つのコンテナは、異なる alias を異なるネットワークでそれぞれ持つことができる。
--link=CONTAINER_NAME:ALIAS
embedded DNS に対して追加の ALIAS (CONTAINER_NAME から参照可能なコンテナの IP アドレスを指すもの) を提供する。
--link を利用すると、その --link が使われたコンテナからのみ参照可能な localized lookup result を提供する。
これにより、新しいコンテナ内のプロセスに対し、 IP や名前を知っていなくても接続可能となる。
--dns=IP_ADDRESS...
コンテナ内の /etc/resolv.conf の nameserver 行に IP アドレスを追加する。
コンテナ内のプロセスは、 /etc/hosts に名前がないときにこの IP アドレスの 53 番ポートを利用して名前解決を試みる。
--dns-search=DOMAIN...
コンテナ内の /etc/resolv.conf の search 行にドメイン名を追加する。
挙動は通常の Linux の /etc/resolv.conf と一緒。
ここ に全部書いてある。
--dns-opt=OPTION...
コンテナ内の /etc/resolv.conf の options 行にオプションを追加する。
挙動は通常の Linux の /etc/resolv.conf と一緒。
ここ に全部書いてある。
※ DNS サーバのアドレスは常に 127.0.0.11 となる。
Ref docs
Configure container DNS
https://docs.docker.com/v17.09/engine/userguide/networking/default_network/configure-dns/
Embedded DNS server in user-defined networks
https://docs.docker.com/v17.09/engine/userguide/networking/configure-dns/
Docker の基本学習 ~ コンテナ間のリンク | Qiita
https://qiita.com/Arturias/items/75828479c1f9eb8d43fa
