9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Dockerのネットワークを調べ直してみた

Last updated at Posted at 2022-04-13
  • 最近 Docker ネットワークについて調べたので、内容をまとめました.
  • Docker のバージョンは20.10.12です。
  • 何かお気づきの点があればコメント頂けるとありがたいです。

抑えておきたいポイント・用語

  • Docker ネットワークを理解する上で押さえておきたい用語や概念をまとめました

OSI 参照モデル

  • 国際標準化機構(ISO)がコンピュータの通信方法を統一するために策定した規格

  • ネットワークを 7 階層に分け、各層のルール(プロトコル)を規定している

  • Docker のネットワークを理解する上で「第 2 層:データリンク層」「第 3 層:ネットワーク層 」を抑える必要がある

    特徴 伝送単位
    ネットワーク層(L3) IP アドレスをもとに、通信相手を識別する パケット
    データリンク層(L2) MAC アドレスをもとに、ネットワーク内の隣接する機器間の通信を制御する フレーム
  • L3:ネットワーク層のデータの転送単位を「パケット」と呼び、「データ」+「ヘッダー(IPアドレス等)」から構成される

  • L2:データリンク層のデータの転送は「フレーム」と呼び、「パケット」+「ヘッダー(MACアドレス等)」から構成される

ブリッジ

  • 複数のネットワーク・セグメントの中継器
  • データリンク層(L2)で動作する
  • どの端末のMACアドレスがどのセグメントに属するかを記憶している
  • データを転送する時は、フレームの MAC アドレスを参照し、宛先の端末が属するセグメントにのみそのフレームを転送する。
  • この時、送信対象のセグメントに属する全ての端末にフレームをブロードキャストする。送信されたフレームは、宛先の端末のみが処理し、それ以外の端末は無視する

仮想ブリッジ

  • ホスト上に仮想的な L2 ネットワークを構成する機能
  • Docker をインストールすると、ホストにdocker0とい名前の仮想ブリッジが作成される

仮想NIC (veth)

  • 仮想的なネットワークインターフェース
  • コンテナを起動すると 下記の veth ペアが作成される
    1. ホストの仮想ブリッジに接続される veth
    2. コンテナに作成される NIC (実体は veth)
  • コンテナとホストの通信はこのveth間で行われる

IPマスカレード

  • グローバルIPアドレスとプライベートIPアドレスを変換する技術
  • 1つのグローバルIPアドレスと複数のポート番号を組み合わせることで、複数のプライベートIPアドレスを変換できる
  • NAPTとも呼ばれる

名前空間

  • 各コンテナのネットワーク空間は独立している。コンテナが属するネットワーク空間を識別する概念。

Docker ネットワーク

  • Dockerネットワークの概念図は以下
  • ホストのNICに仮想ブリッジが接続される。Dockerが利用する仮想ブリッジのデフォルトはdocker0
  • ホストの仮想ブリッジに仮想NIC(veth)が接続される
  • ホストの仮想NIC(veth)とコンテナのNICが通信する
  • 各コンテナのネットワークは分離している(名前空間が異なる)
  • コンテナが外部と通信する際、コンテナのプライベートIPが、ホスト側のグローバルIPでIPマスカレードされる

docker-network-01.png

Dockerネットワークの種類

bridge

  • ホストの仮想ブリッジを利用するネットワーク
  • Dockerをインストールすると、デフォルトでbridgeという名前のbridgeネットワークが作成される
  • docker network createでDockerネットワークを作成する際、-dオプションに未指定 または bridgeを指定した場合、bridgeネットワークが作成される
  • docker runでコンテナを起動する際、--netに未指定 または bridgeを指定した場合、デフォルトのbridgeネットワークが利用される。
    • デフォルトのbridgeに対応する仮想ブリッジはdocker0

host

  • ホストの物理NICを直接利用して外部と接続するネットワーク (ホストとコンテナのネットワーク設定が同じ)
  • Dockerをインストールすると、デフォルトでhostという名前のhostネットワークが作成される

none

  • コンテナをホストのネットワークに接続しない
  • Dockerをインストールすると、デフォルトでnoneという名前で空のネットワークが作成される

docker-compose を利用する場合

  • docker-compose でコンテナを起動する際、networksを指定しなかった場合、<Composeファイルの配置先ディレクトリ>_defaultという名前のbridgeネットワークが作成される
  • この時作成されるbridgeネットワークに対応する仮想ブリッジは、docker-composeでコンテナを起動した際、自動で作成される
  • docker-compose で起動したコンテナをhostネットワークに接続する場合、network_modehostを指定する

動作検証1( docker コマンドを利用する場合)

ホストのDocker ネットワーク一覧

  • ホストに作成されているDockerネットワークを確認する。docker network lsを実行

  • 結果は以下。bridge / host / none のネットワークが作成されていることがわかる

    NETWORK ID     NAME                DRIVER    SCOPE
    64f5cef2d77d   bridge              bridge    local                                                                                                                                                                
    f887f0e6ecc7   host                host      local                                                                                                                                                                
    8d87bf258e89   none                null      local                                                                                                                                                                
    

ホストのネットワークを確認する

  • ip aを実行。

  • 結果は以下。docker0 仮想ブリッジが作成されていることがわかる

  • docker0に割り当てられているIPアドレスは 172.17.0.1/16

    6: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
      link/ether 02:42:9b:df:82:32 brd ff:ff:ff:ff:ff:ff
      inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
      <略>
    

コンテナを起動する

  • 下記のコマンドでコンテナを起動する

    docker run -d --name my-nginx -p 8081:80 nginx
    

ホストのDocker ネットワークの一覧

  • 再度、ホストに作成されているDockerネットワークをdocker network lsで確認する

  • 結果は以下。コンテナ起動前と同じ。新たなネットワークは作成されていない

    NETWORK ID     NAME                DRIVER    SCOPE
    64f5cef2d77d   bridge              bridge    local
    f887f0e6ecc7   host                host      local
    8d87bf258e89   none                null      local
    

Docker ネットワークの確認

  • docker network inspect bridgeで、bridgeネットワークの詳細を確認する
  • 結果は以下の通り
    • ゲートウェイアドレスが172.17.0.1で、docker0に設定されているアドレスと一致している
    • コンテナには172.17.0.2/16のアドレスが割り振られている
$ docker network inspect bridge                                                                                                                                                                                   [
    {
        "Name": "bridge",
        "Id": "1e38e4596ba1f79f4b29cfd865b0572e0dcda647eddb68d34639f0c6717b2393",
        "Created": "2022-04-09T23:39:22.72754133Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "eab19be6f0a5267829d26c93143214cc9b384383506439a7bbdc067e2a1196c5": {
                "Name": "my-nginx",
                "EndpointID": "6679fdcf5b08cde2019cbeb75cfa5f0a3cae8155087508be5c7c89317689ab1d",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

コンテナのネットワークを確認する

  • docker exec -itにより、起動したコンテナにログインし、ip aによりネットワーク設定を確認する
  • 結果は以下の通り。(docker inspectの実行結果から確認した)、コンテナに割り振られたIPアドレス172.17.0.2がコンテナのNICのIPアドレスに設定されている
  10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
    <略>

動作検証2( docker-compose を利用する場合)

確認用の docker-compose の作成

  • sample001 ディレクトリを作成し、下記の docker-compose ファイルを直下に配置する

    services:
      nginx1:
        container_name: my-nginx1
        image: nginx:latest
        ports:
        - 8081:80/tcp
      nginx2:
        container_name: my-nginx2
        image: ngninx:latest
        ports:
        - 8082:80/tcp
    

docker-compose でコンテナを起動する

  • docker-compose up -d --buildを実行
  • 結果は以下。
    • デフォルトのドライバ設定(=bridge)で、sample001_defaultネットワークを作成していることがわかる
    Creating network "sample001_default" with the default driver                                                                                                                                                      
    Pulling nginx1 (nginx:latest)...                                                                                                                                                                                  
      :
      略
      :
    Status: Downloaded newer image for nginx:latest                                                                                                                                                                   
    Creating my-nginx1 ... done                                                                                                                                                                                       
    Creating my-nginx2 ... done                                                       
    

Docker ネットワークの一覧

  • docker network lsを実行。
  • 結果は以下。sample001_default という bridge ネットワークが新たに作成されている
    NETWORK ID     NAME                DRIVER    SCOPE
    64f5cef2d77d   bridge              bridge    local                                                                                                                                                                
    f887f0e6ecc7   host                host      local                                                                                                                                                                
    8d87bf258e89   none                null      local                                                                                                                                                                
    a2808b008bb9   sample001_default   bridge    local   ★ 新たに作成されたネットワーク
    

ホストのネットワークを確認する

  • ホストのネットワークを確認する。ip aを実行

  • 結果は以下の通り。

    • 仮想ブリッジ(16: br-f03cb12e5aff) と 仮想NICが2つ (18, 20:vetchXXX) 作成されている
    • 各仮想NIC(vethXXXX)は仮想ブリッジ(br-f03cb12e5aff)に接続されている
    16: br-f03cb12e5aff: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
      link/ether 02:42:69:48:b3:f7 brd ff:ff:ff:ff:ff:ff
      inet 172.20.0.1/16 brd 172.20.255.255 scope global br-f03cb12e5aff
      略
    18: vethe513542@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-f03cb12e5aff state UP group default
      link/ether ca:a3:f2:32:c4:bc brd ff:ff:ff:ff:ff:ff link-netnsid 0
      略
    20: veth251227c@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-f03cb12e5aff state UP group default
      link/ether 0a:7a:ad:98:98:b4 brd ff:ff:ff:ff:ff:ff link-netnsid 1
      略
    

ネットワークブリッジを確認する

  • brctl showで、ホストのネットワークブリッジの設定を確認する

  • 結果は以下。

    • 仮想ブリッジ(16: br-f03cb12e5aff)に仮想NIC(vethe513542/veth251227c)が接続されていることがわかる
    bridge name        bridge id               STP enabled     interfaces                                                                                                                                                
    br-f03cb12e5aff    8000.02426948b3f7       no              veth251227c  vethe513542
    

Dockerネットワークの詳細を確認する

  • sample001_defaultの詳細を確認する。docker network inspect sample001_defaultを実行。
  • 結果は以下の通り。
    • サブネットは、172.20.0.0
    • ゲートウェイは、172.20.0.1。これは、docker-composeで作成された仮想ブリッジ(br-5870201d8e2b)のIPアドレスと一致
    • コンテナには、172.20.0.3172.20.0.2が設定されている。
    [                                                                                                                                                                                                                     
      {                                                                                                                                                                                       
         "Name": "sample001_default",
         "Id": "f03cb12e5affb4261fd8c8959596848b5d2b82efa9e0b7fd777446f74c27b8d7",
         "Created": "2022-04-10T08:58:16.43048963+09:00",
         "Scope": "local",
         "Driver": "bridge",
         "EnableIPv6": false,
         "IPAM": {                                                                                                                                                                                                             
           "Driver": "default",
           "Options": null,                                                                                                                                                                                                  
           "Config": [
             {                                                                                                                                                                                                                     
               "Subnet": "172.20.0.0/16",
               "Gateway": "172.20.0.1"
             }
           ]
         },
         "Internal": false,
         "Attachable": true,
         "Ingress": false,
         "ConfigFrom": {
           "Network": ""
         },
         "ConfigOnly": false,
         "Containers": {
            "c2030004bc1daeb7b266715035fd9bbc4b97d03dc9c39199bb9ed04a00b43896": {
               "Name": "my-nginx1",
               "EndpointID": "9191d6c32b88b3642b95869084133e009e24f48e2c94bf79d670fa98a2295e5a",
               "MacAddress": "02:42:ac:14:00:03",
               "IPv4Address": "172.20.0.3/16",
               "IPv6Address": ""
            },
            "e73a7929bc179c2e308674b1f71c722bf6f88ce7add8cb6db056a72dbd412dba": {
               "Name": "my-nginx2",
               "EndpointID": "590b155e49faab6ea091bb1f32af55241fa9d338250baa3f7dbaead29ce791c9",
               "MacAddress": "02:42:ac:14:00:02",
               "IPv4Address": "172.20.0.2/16",
               "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
           "com.docker.compose.network": "default",
           "com.docker.compose.project": "sample001",
           "com.docker.compose.version": "1.25.0"
        }
      }
    ]
    

コンテナのネットワークを確認する

  • docker exec -itで各コンテナに入り、ip aでネットワークを確認する。
  • 結果は以下の通り。
    • docker inspect で表示されている通り、各コンテナに割り振られた IP アドレスが NIC に設定されている。
    # コンテナ1(my-nginx1)
    19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
      link/ether 02:42:ac:14:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
      inet 172.20.0.3/16 brd 172.18.255.255 scope global eth0
         valid_lft forever preferred_lft forever
    
    # コンテナ2(my-nginx2)
    17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
      link/ether 02:42:ac:14:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
      inet 172.20.0.2/16 brd 172.18.255.255 scope global eth0
         valid_lft forever preferred_lft forever
    

以上

9
8
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
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?