LoginSignup
5
3

More than 3 years have passed since last update.

Docker で コンテナに DNS サーバーを指定したときの IPの衝突によって名前解決できなくなる現象の確認

Last updated at Posted at 2019-01-08

結論

  • dockerの dns オプションを指定した際は、docker networkとの衝突に注意が必要
    • コンテナ内から名前解決できなくなる
  • 以下の2つは等価ではない
    • docker の dns オプションを指定しない(デフォルトを使用する)
    • ホスト側DNSサーバーIPアドレス(例えば 192.168.0.1) を dockerの dns オプションに指定する

条件

  • Windows 10 Home
    • ProではないのでHyper-Vが使えない
    • → Docker for Windows が使えない
  • VirtualBox
  • Docker Machine

docker --version

Docker version 18.03.0-ce, build 0520e24302

古い。。。
TODO: 後で更新

docker-machine --version

docker-machine.exe version 0.14.0, build 89b8332

docker-machine ip

192.168.99.100

ネットワーク

ホスト側のDNSサーバー

192.168.0.1

ipconfig.exe /all

抜粋

イーサネット アダプター VirtualBox Host-Only Network #5:
   接続固有の DNS サフィックス . . . . .:
   説明. . . . . . . . . . . . . . . . .: VirtualBox Host-Only Ethernet Adapter #5
   IPv4 アドレス . . . . . . . . . . . .: 192.168.56.1(優先)
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .:
   DNS サーバー. . . . . . . . . . . . .: fec0:0:0:ffff::1%1
                                          fec0:0:0:ffff::2%1
                                          fec0:0:0:ffff::3%1


イーサネット アダプター VirtualBox Host-Only Network #6:
   接続固有の DNS サフィックス . . . . .:
   説明. . . . . . . . . . . . . . . . .: VirtualBox Host-Only Ethernet Adapter #6
   IPv4 アドレス . . . . . . . . . . . .: 192.168.99.1(優先)
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .:
   DNS サーバー. . . . . . . . . . . . .: fec0:0:0:ffff::1%1
                                          fec0:0:0:ffff::2%1
                                          fec0:0:0:ffff::3%1


イーサネット アダプター ローカル エリア接続:
   接続固有の DNS サフィックス . . . . .:
   IPv4 アドレス . . . . . . . . . . . .: 192.168.0.13(優先)
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .: 192.168.0.1
   DHCP サーバー . . . . . . . . . . . .: 192.168.0.1
   DNS サーバー. . . . . . . . . . . . .: 192.168.0.1

検証方法

  • コンテナ内にDNSサーバーを起動
    • ベース: tksugimoto/docker-dns-proxy-logger
    • dnsmasq を使用
    • DNSサーバーはホスト側のDNSサーバーへ転送するだけ
      • 192.168.0.1
    • docker-machine を使用しているため、 作成したDNSサーバーのIPは 192.168.99.100
  • ホスト側からコンテナ内にDNSサーバーにnslookup

検証結果

dns指定無しの場合

docker networkのいずれかとホスト側のDNSサーバーのIPと衝突しててもコンテナ内で 名前解決はできる

nslookup

$ winpty nslookup.exe example.com 192.168.99.100
サーバー:  UnKnown
Address:  192.168.99.100

権限のない回答:
名前:    example.com
Address:  93.184.216.34

192.168.99.100 は問い合わせに使うDNSサーバーのIP(コンテナ内DNSサーバー)

docker network

ホストのDNSサーバーのIP 192.168.0.1my-network-13 (192.168.0.0/20) と衝突している

$ docker network inspect $(docker network ls -q) | grep -E "Subnet|Name" | grep -C5 192.168.0.0
        "Name": "my-network-11",
                    "Subnet": "172.30.0.0/16",
        "Name": "my-network-12",
                    "Subnet": "172.31.0.0/16",
        "Name": "my-network-13",
                    "Subnet": "192.168.0.0/20",
        "Name": "my-network-14",
                    "Subnet": "192.168.16.0/20",
        "Name": "my-network-15",
                    "Subnet": "192.168.32.0/20",
        "Name": "my-network-16",

※ docker networkを大量に作る方法 → docker networkを限界まで作る - Qiita

docker-compose.yml

dns オプションは未指定(デフォルト値が使われる)

version: '3'

services:
  dns-server:
    build:
      context: ./
      args:
        - http_proxy
        - https_proxy
    ports:
      - "192.168.99.100:53:53"
      - "192.168.99.100:53:53/udp"
    restart: always

dns指定ありの場合(docker networkとIPが衝突した場合)

名前解決がタイムアウトする

DNSサーバーへ到達できていないと考えられる

nslookup

$ winpty nslookup.exe example.com 192.168.99.100
DNS request timed out.
    timeout was 2 seconds.
サーバー:  UnKnown
Address:  192.168.99.100

DNS request timed out.
    timeout was 2 seconds.
DNS request timed out.
    timeout was 2 seconds.

192.168.99.100 は問い合わせに使うDNSサーバーのIP(コンテナ内DNSサーバー)

docker network

ホストのDNSサーバーのIP 192.168.0.1my-network-13 (192.168.0.0/20) と衝突している

$ docker network inspect $(docker network ls -q) | grep -E "Subnet|Name" | grep -C5 192.168.0.0
        "Name": "my-network-11",
                    "Subnet": "172.30.0.0/16",
        "Name": "my-network-12",
                    "Subnet": "172.31.0.0/16",
        "Name": "my-network-13",
                    "Subnet": "192.168.0.0/20",
        "Name": "my-network-14",
                    "Subnet": "192.168.16.0/20",
        "Name": "my-network-15",
                    "Subnet": "192.168.32.0/20",
        "Name": "my-network-16",

docker-compose.yml

dns オプションに 192.168.0.1 を指定

version: '3'

services:
  dns-server:
    build:
      context: ./
      args:
        - http_proxy
        - https_proxy
    ports:
      - "192.168.99.100:53:53"
      - "192.168.99.100:53:53/udp"
    dns:
      - 192.168.0.1
    restart: always

dns指定ありの場合(docker networkとIPが衝突してない場合)

一つ前の条件から docker networkが削除削除された状態

docker network prune

名前解決できる

nslookup

$ winpty nslookup.exe example.com 192.168.99.100
サーバー:  UnKnown
Address:  192.168.99.100

権限のない回答:
名前:    example.com
Address:  93.184.216.34

192.168.99.100 は問い合わせに使うDNSサーバーのIP(コンテナ内DNSサーバー)

docker network

my-network-13 (192.168.0.0/20) は削除されたため、 ホストのDNSサーバーのIP 192.168.0.1と衝突している docker networkは存在しない

$ docker network inspect $(docker network ls -q) | grep -E "Subnet|Name" | grep -C5 192.168.0.0        
# (存在しない)

docker-compose.yml

dns オプションに 192.168.0.1 を指定

version: '3'

services:
  dns-server:
    build:
      context: ./
      args:
        - http_proxy
        - https_proxy
    ports:
      - "192.168.99.100:53:53"
      - "192.168.99.100:53:53/udp"
    dns:
      - 192.168.0.1
    restart: always

まとめ

  • dockerの dns オプションを指定した際は、docker networkとの衝突に注意が必要
    • コンテナ内から名前解決できなくなる
  • 以下の2つは等価ではない
    • docker の dns オプションを指定しない(デフォルトを使用する)
    • ホスト側DNSサーバーIPアドレス(例えば 192.168.0.1) を dockerの dns オプションに指定する
5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3