Dockerのデフォルトbridgeネットワーク(docker0)について調べたメモ

Pocket

Dockerのネットワークについてまずはデフォルトのネットワークbridge(ネットワーク・インターフェース名:docker0)について、実際に試しながら調べた内容をメモします。

前提

  • DockerをUbuntuにインストール
    • Ubuntu: 20.04.4 LTS
    • Docker: 20.10.16

Ref

Dockerのネットワーク ドライバー

  • bridge
  • host
  • none

ブリッジの一般的な意味。

ブリッジ(Bridge/L2スイッチ) ネットワークをデータリンク層で延長する装置

— マスタリングTCP/IP 入門編 p38

bridgeネットワークの概要

  • ネットワークを指定しないで起動したコンテナはデフォルトのbridgeネットワークに接続
    • デフォルトのbridgeネットワークのネットワーク・インターフェースはdocker01
    • デフォルトのbridgeネットワークに接続されたコンテナ間はIPアドレスで通信可能
    • デフォルトのbridgeネットワークに接続されたコンテナ間はコンテナ名で通信不可(デフォルトのbridgeネットワークは内蔵DNSサーバを持たないため)
  • 新規作成したbridgeネットワークに接続されたコンテナ間はコンテナ名で通信可能
  • Docker Composeは、自動でbridgeネットワークを新規作成するのでservice`名[^serivice名]で通信可能

デフォルトネットワーク

Dockerをインストールしたらデフォルトでネットワーク名がbridgehostnullのネットワークが作成されます。

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

上述したとおりデフォルトで作成されるbridgeネットワークのネットワークインターフェースがdoker0になります(Ubuntuの場合2)。

Docker のインストールは、自動的に3つのネットワークを作成します。

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

Docker をインストールした全ての環境には、 docker0 と表示されるブリッジ( bridge )ネットワークが現れます。オプションで docker run –net=<ネットワーク名> を指定しない限り、Docker デーモンはデフォルトでこのネットワークにコンテナを接続します。ホスト上で ifconfig コマンドを使えば、ホストネットワーク上のスタックの一部として、このブリッジを見ることができます。

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

デフォルトのbridgeネットワーク

  • デフォルトのbridgeネットワークのネットワーク・インターフェースはdocker0になります
  • ネットワークを指定せずに起動したコンテナはデフォルトのbridgeネットワークに接続されます

ネットワークインターフェース

ホストは以下のネットワーク・インターフェースを持つと仮定します。

  • eth0:ホストのデフォルトのネットワーク・インターフェース
  • docker0:デフォルトのbridgeネットワークのネットワーク・インターフェース

コンテナ同士の通信

IPアドレス3を使ったコンテナ間通信においてdocker0に発生するデータをキャプチャしてみます。

$ docker run -itd --name alpine-sample1 alpine:latest
$ docker run -itd --name sample-sample2 alpine:latest

コンテナのIPアドレスを確認します。

$ sudo docker exec -it alpine-sample1 /bin/sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          ...
  • alpine-sample1のIPアドレスは172.17.0.2です
  • 同様にalpine-sample2のIPアドレスは172.17.0.3とします

コンテナ間はdocker0で通信していることを確認します4

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

alpine-sample1からalpine-sample2pingを発行します。

$ docker exec -it alpine /bin/sh
/ # ping -c 1 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.110 ms

予想どおりdocker0に通信が発生しています。

$ sudo tcpdump -tnl -i docker0 icmp                                                                                                                        [15/84]
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

.....
IP 172.17.0.2 > 172.17.0.3: ICMP echo request, id 12, seq 0, length 64
IP 172.17.0.3 > 172.17.0.2: ICMP echo reply, id 12, seq 0, length 64

コンテナとインターネットの通信

外部との通信を確認します。
例としてGoogleが提供するフルサービスリゾルバ8.8.8.8pingを発行します。

$ sudo docker exec -it alpine-sample1 /bin/sh
/ # ping -c 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=101 time=3.000 ms

--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.000/3.000/3.000 ms

予想どおりdocker0に通信が発生しています。

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

.....
IP 172.17.0.2 > 8.8.8.8: ICMP echo request, id 27, seq 0, length 64
IP 8.8.8.8 > 172.17.0.2: ICMP echo reply, id 27, seq 0, length 64

加えてホストのデフォルトのネットワークインターフェースeth0にも通信が発生していることが分かります。

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

...
IP 10.3.0.183 > 8.8.8.8: ICMP echo request, id 27, seq 0, length 64
IP 8.8.8.8 > 10.3.0.183: ICMP echo reply, id 27, seq 0, length 64

外部からのアクセス

外部からコンテナにアクセスする際の通信をみます。
例としてhttpd:latestを稼働しているホストに外部からアクセスした際の通信をみます。

前提

  • ホスト
    • グローバルIPアドレス:203.0.113.1
    • プレイベートIPアドレス:192.0.2.1/24
    • ネットワーク・インターフェース
      • eth0
      • docker0
  • コンテナ
    • プライベートIPアドレス:172.17.0.4
    • ネットワーク・インターフェース
      • eth0
  • クライアント
    • グローバルIPアクセス:203.0.113.150

httpd:latestifconfigがインストールされていないのでapt install net-toolsでインストールします。

コンテナ起動

$ sudo docker run -d -p 8000:80 --name httpd-sample httpd

通信を確認

クライアントのブラウザで http://203.0.113.1:8000 にアクセスします。

ホストのeth0の通信をみます。
クライアントとホストはポート8000番で通信しています。

$ sudo tcpdump -tnl -i eth0 tcp port 8000                                                                                                           [19/1972]
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

IP 203.0.113.150.64640 > 192.0.2.1.8000: Flags [S], seq 218777360, win 65535, options [mss 1394,nop,wscale 6,nop,nop,TS val 3364579648 ecr 0,sackOK,eol], length 0
IP 192.0.2.1.8000 > 203.0.113.150.64640: Flags [S.], seq 1645943187, ack 218777361, win 65160, options [mss 1460,sackOK,TS val 2400436806 ecr 3364579648,nop,wscale 6], length 0
IP 203.0.113.150.64639 > 192.0.2.1.8000: Flags [.], ack 1, win 2051, options [nop,nop,TS val 1426504603 ecr 2400436806], length 0

ホストのdocker0の通信をみます。
コンテナとポート80番で通信しています。

$ sudo tcpdump -tnl -i docker0 tcp port 80                                                                                                          [19/1804]
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

IP 203.0.113.150.64640 > 172.17.0.4.80: Flags [S], seq 218777360, win 65535, options [mss 1394,nop,wscale 6,nop,nop,TS val 3364579648 ecr 0,sackOK,eol], length 0
IP 172.17.0.4.80 > 203.0.113.150.64640: Flags [S.], seq 1645943187, ack 218777361, win 65160, options [mss 1460,sackOK,TS val 2400436806 ecr 3364579648,nop,wscale 6], length 0
IP 203.0.113.150.64639 > 172.17.0.4.80: Flags [.], ack 1, win 2051, options [nop,nop,TS val 1426504603 ecr 2400436806], length 0

コンテナのeth0の通信をみます。
予想どおりポート80番で通信しています。

# tcpdump -tnl -i eth0 tcp port 80
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes

IP 203.0.113.150.64640 > 172.17.0.4.80: Flags [S], seq 218777360, win 65535, options [mss 1394,nop,wscale 6,nop,nop,TS val 3364579648 ecr 0,sackOK,eol], length 0
IP 172.17.0.4.80 > 124.18.121.200.64640: Flags [S.], seq 1645943187, ack 218777361, win 65160, options [mss 1460,sackOK,TS val 2400436806 ecr 3364579648,nop,wscale 6], length 0
IP 124.18.121.200.64639 > 172.17.0.4.80: Flags [.], ack 1, win 2051, options [nop,nop,TS val 1426504603 ecr 2400436806], length 0

簡単ですが外部からのコンテナに対するアクセスついて確認しました。


  1. Macの場合はbridge0です。
    [^service名]:Docker Composeは各コンテナをserviceと呼びます。 

  2. Macはbridge0になります。 

  3. コンテナ名で通信する場合はdocker0ではなく、docker network create {{network_name}}で作成したネットワークを設定してコンテナを起動します。 

  4. Macで同様のことを試しましたがbridge0の通信をキャプチャできませんでした。 

コメント

No comments yet.

コメントの投稿

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