Ubuntu 16.04 LTS における解決方法のまとめは → こちら
- Docker Swarmのworkerノード(コンテナホスト)がConsulクラスタに組入れられている
- workerノード上ではdnsmasqが動いていて、ノード上では「consul.service.consul」的な名前が解決可能である
- Docker version 17.06.2-ce
- Docker Swarm Mode上のservice内で、「consul.service.consul」的な名前を使いたい
- Swarm以外のコンテナ内でも「consul.service.consul」的な名前を使いたい
- 例えば、自前のアプリケーションはSwarm上で動作させるが、cAdvisorはSwarm外で直接コンテナ起動することを想定
- つまり、
レジストリは registry.service.consul でアクセスしたい。
アプリ内からは、Redisに redis.service.consul でアクセスしたい。
Dockerコンテナ内の /etc/resolv.conf
はこのようになる
$ docker run -it --rm centos /bin/sh
sh# cat /etc/resolv.conf
search ****.jp (プロバイダのドメイン)
nameserver 8.8.8.8
nameserver 8.8.4.4
自動的にGoogleのDNSが設定される。 (このページの末尾参照) これにより、外部の名前は解決可能となるが、(当然ながら) Consulの名前は解決できない。
Dockerコンテナ起動時に、DNSとしてDockerホストを参照するように指定する。
$ docker run -it --rm --dns=172.17.0.1 centos /bin/sh
sh# cat /etc/resolv.conf
search ****.jp (プロバイダのドメイン)
nameserver 172.17.0.1
あるいは、/etc/docker/daemon.json
に
{
"dns": ["172.17.0.1"]
}
と記述したうえでDNS指定せずに起動する
$ docker run -it --rm centos /bin/sh
sh# cat /etc/resolv.conf
search ****.jp (プロバイダのドメイン)
nameserver 172.17.0.1
これにより、外部の名前だけでなく ping consul.service.consul
も通るようになる。
常にConsulを利用するからといって、daemon.json
にDNS記述を書いては いけない 。
Swarmで起動しているコンテナでは
sh# cat /etc/resolv.conf
search *****.jp (プロバイダのドメイン)
nameserver 127.0.0.11
options ndots:0
となっている。ここで 127.0.0.11
は「Docker内蔵DNSサーバ」。
Swarmのサービス(が動いているコンテナ)の名前は解決できるが、外部の名前も、Consulの名前も解決できない。 起動方法が生コンテナなのかSwarmコンテナなのか、また、DNS指定がdaemon.jsonなのかコマンドラインオプションなのか、で挙動が異なることがわかった。
Swarmコンテナはdocker-compose.ymlでもDNSを指定しない
(A-1) 生コンテナ | (A-2) Swarmコンテナ | |
---|---|---|
/etc/resolv.conf | search xxxxxxx.jp nameserver 172.17.0.1 |
search xxxxxxx.jp nameserver 127.0.0.11 options ndots:0 |
ping www.goo.ne.jp | OK | NG |
ping consul.service.consul | OK | NG |
ping (swarmサービス) | NG | OK |
Swarmコンテナはdocker-compose.ymlでもDNSを指定しない
(B-1) 生コンテナ | (B-2) Swarmコンテナ | |
---|---|---|
/etc/resolv.conf | search xxxxxxx.jp nameserver 172.17.0.1 |
search xxxxxxx.jp nameserver 127.0.0.11 options ndots:0 |
ping www.goo.ne.jp | OK | OK |
ping consul.service.consul | OK | OK |
ping (swarmサービス) | NG | OK |
- 生コンテナの場合は、コマンドラインでのDNS指定とdaemon.jsonでのDN指定は同じ挙動
- Swarmコンテナの場合は、DNS指定をコマンドラインで行うかdaemon.jsonで行うかで挙動が変わる
次のようにDNS指定を扱うことで、Dockerコンテナ(通常コンテナ & Swarmサービスの両方)で ConsulのDNSを解決することができる。
daemon.json
にDNSを記述してはいけないdocker run --dns=
で記述する。(systemdで扱う場合にはUNITファイルで記述する)
このような挙動の差異がなぜ生じるのか、さらに調査する。 (Swarm Modeでの内蔵DNSの挙動について明らかにする)