Dockerのbridgeネットワーク&内臓DNSサーバ&サービスディスカバリ

Pocket

Dockerのユーザー定義のbiridgeネットワークを作成して、サービス・ディスカバリについて調べたメモです。

bridgeネットワーク作成

デフォルトネットワークを確認

デフォルトのネットワークを再度確認してみます。

$ sudo docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
abf0a3a6242a   bridge    bridge    local     <--- このネットワークのネットワーク・インターフェースがLinuxはdocker0、Macはbridge0
5647050e2ccb   host      host      local
f17799accf48   none      null      local

bridgeネットワークを新規作成

$ docker network create {{network_name}}
  • ネットワークを追加するとbr-で始まるネットワーク・インターフェースがホストに作成されます
  • br-xxxxxのxxxxxは、NEWORK IDです
  • NTWORK IDはdocker network lsで確認します

例)

$ docker network create sample
$sudo docker network ls

NETWORK ID     NAME      DRIVER    SCOPE
abf0a3a6242a   bridge    bridge    local
5647050e2ccb   host      host      local
f17799accf48   none      null      local
8fe0215332a8   sample    bridge    local <--- 新規に作成

ホストでifconfigでネットワーク・インターフェースを確認。

$ ifconfig
br-8fe0215332a8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500     // <--- 新規に追加
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        inet6 fe80::42:87ff:fe57:24b2  prefixlen 64  scopeid 0x20<link>
        ether 02:42:87:57:24:b2  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5  bytes 526 (526.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:37ff:fe8d:b952  prefixlen 64  scopeid 0x20<link>
        ether 02:42:37:8d:b9:52  txqueuelen 0  (Ethernet)
        RX packets 1392  bytes 85837 (85.8 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2875  bytes 13382135 (13.3 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 10.3.0.183  netmask 255.255.255.0  broadcast 10.3.0.255
        inet6 fe80::4b5:10ff:fe1f:21cd  prefixlen 64  scopeid 0x20<link>
        ether 06:b5:10:1f:21:cd  txqueuelen 1000  (Ethernet)
        RX packets 66248  bytes 76218429 (76.2 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 96440  bytes 23585335 (23.5 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

新規bridgeネットワークを使った通信

netオプションで作成したbridgeネットワークを指定してコンテナを起動します。

$ sudo docker run -itd --name alpine1 --net sample alpine:latest
$ sudo docker run -itd --name alpine2 --net sample alpine:latest

ネットワーク・インターフェースbr-8fe0215332a8を使用していることを確認します。

$ sudo tcpdump -tnl -i br-8fe0215332a8 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-8fe0215332a8, link-type EN10MB (Ethernet), capture size 262144 bytes

コンテナ名alpine2でアクセスします(デフォルトのネットワーク・インターフェースdocker0はIPアドレスでしかアクセスできません)。
コンテナ名でアクセスできるのは、bridgeネットワーク(デフォルトのbridgeネットワークを除く)が内蔵DNSサーバを持っているからです1

デフォルトの「bridge0」という名称のブリッジ・ネットワークでは、この名前解決機能がありません。コンテナ間の通信でサービス・ディスカバリを有効化するには、自分でブリッジ・ネットワークを作成する必用があります。これをDockerではUser Defined Bridge Network(ユーザ定義ブリッジ・ネットワーク)と呼びます。

— https://knowledge.sakura.ad.jp/23899/

内蔵DNSサーバを使用してコンテナ名(Docker Composeではサービス名)でアクセスする機能をサービス・ディスカバリと呼びます。

$ sudo docker exec -it alpine1 /bin/sh
/ # ping -c 1 alpine2 // <------------------------ コンテナ名でPingを発行
PING alpine2 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.103 ms

--- alpine2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.103/0.103/0.103 ms
sudo tcpdump -tnl -i br-8fe0215332a8 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-8fe0215332a8, link-type EN10MB (Ethernet), capture size 262144 bytes

IP 172.18.0.3 > 172.18.0.2: ICMP echo request, id 14, seq 0, length 64
IP 172.18.0.2 > 172.18.0.3: ICMP echo reply, id 14, seq 0, length 64

bridgeネットワークの内蔵DNSサーバ

新規に作成するbridgeネットワークは内蔵DNSサーバを持ちます。

Docker デーモンは内蔵 DNS サーバを動かし、ユーザ定義ネットワーク上でコンテナがサービス・ディスカバリを自動的に行えるようにします。コンテナから名前解決のリクエストがあれば、内部 DNS サーバを第一に使います。リクエストがあっても内部 DNS サーバが名前解決できなければ、外部の DNS サーバにコンテナからのリクエストを転送します。割り当てできるのはコンテナの作成時だけです。内部 DNS サーバが到達可能なのは 127.0.0.11 のみであり、コンテナの resolv.conf に書かれます。ユーザ定義ネットワーク上の内部 DNS サーバに関しては ユーザ定義ネットワーク用の内部 DNS サーバ をご覧ください。

— https://docs.docker.jp/engine/userguide/networking/dockernetworks.html

上述のalpine1コンテナにdigを入れて内蔵DNSサーバを確認します。

$ sudo docker exec -it alpine1 /bin/sh
/ # apt update
/ # apk add --no-cache bind-tools   // <------------------------ digをインストール
fetch https://dl-cdn.alpinelinux.org/alpine/v3.15/main/x86_64/APKINDEX.tar.gz
.....
OK: 13 MiB in 29 packages
/ # dig alpine2    // <------------------------ サービス・ディスカバリを見る

; <<>> DiG 9.16.27 <<>> alpine2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35236
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;alpine2.                       IN      A

;; ANSWER SECTION:
alpine2.                600     IN      A       172.18.0.2

;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)   <---- 内蔵DNSサーバ
;; WHEN: Sat May 14 07:26:26 UTC 2022
;; MSG SIZE  rcvd: 48

  1. デフォルトのbridgeネットワークのネットワーク・インターフェースがLinuxではdocker0、Macではbridge0です。) 

コメント

No comments yet.

コメントの投稿

改行と段落タグは自動で挿入されます。
メールアドレスは表示されません。