Docker ネットワークの基礎

DockerBeginner
オンラインで実践に進む

はじめに

この実験(Lab)では、Docker ネットワークの基礎を学びます。Docker ネットワークを利用することで、コンテナ同士や、コンテナと外部世界との通信が可能になります。ここでは、さまざまなネットワークタイプの紹介、カスタムネットワークの作成、コンテナの接続、およびネットワーク設定の管理について説明します。この実践的な体験を通じて、Docker ネットワークの概念と実務に関する強固な基礎を築くことができます。

Docker ネットワークの種類を理解する

Docker には、いくつかの組み込みネットワークドライバが用意されています。まずは、システム上のデフォルトネットワークを確認することから始めましょう。

ターミナルで次のコマンドを実行して、利用可能なすべての Docker ネットワークを表示します。

docker network ls

このコマンドは、Docker がシステム上に作成したすべてのネットワークをリストアップします。次のような出力が表示されるはずです。

NETWORK ID     NAME      DRIVER    SCOPE
79dce413aafd   bridge    bridge    local
91199fc6ad2e   host      host      local
1078d2c781b6   none      null      local

デフォルトのネットワークタイプについて解説します:

  1. bridge(ブリッジ):これはデフォルトのネットワークドライバです。ネットワークを指定せずにコンテナを起動すると、自動的にこのブリッジネットワークに接続されます。同じブリッジネットワーク上のコンテナは、それぞれの IP アドレスを使用して相互に通信できます。

  2. host(ホスト):このドライバは、コンテナと Docker ホスト間のネットワーク分離を取り除きます。コンテナはホストのネットワーク名前空間を共有するため、ホストの IP アドレスとポート空間を直接使用します。これは、特定のシナリオでパフォーマンスを最適化するのに役立ちます。

  3. none:このドライバは、コンテナのすべてのネットワーク機能を無効にします。このネットワークタイプを使用するコンテナは、外部ネットワークや他のコンテナにアクセスできなくなります。コンテナを完全に隔離したい場合に便利です。

SCOPE 列は、ネットワークが単一のホストに限定されているか(local)、Docker Swarm 内の複数のホストにまたがることができるか(swarm)を示しています。

デフォルトブリッジネットワークの調査

ネットワークの一覧を確認したので、次はデフォルトのブリッジネットワークを詳しく見てみましょう。このネットワークは Docker によって自動的に作成され、特に指定がない限りコンテナによって使用されます。

次のコマンドを実行して、ブリッジネットワークの詳細情報を表示(インスペクト)します。

docker network inspect bridge

このコマンドは、サブネット、ゲートウェイ、接続されているコンテナなど、ブリッジネットワークに関する詳細な情報を提供します。次のような出力が表示されます(簡略化のため一部省略しています)。

[
  {
    "Name": "bridge",
    "Id": "79dce413aafdd7934fa3c1d0cc97decb823891ce406442b7d51be6126ef06a5e",
    "Created": "2024-08-22T09:58:39.747333789+08:00",
    "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": {},
    "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": {}
  }
]

出力結果の主要な項目について説明します:

  • Subnet(サブネット):このネットワーク内のコンテナが使用するサブネットは 172.17.0.0/16 です。これは、コンテナにこの範囲内の IP アドレスが割り当てられることを意味します。
  • Gateway(ゲートウェイ):このネットワークのゲートウェイは 172.17.0.1 です。これは、コンテナが自身のネットワーク外と通信する際に使用する IP アドレスです。
  • Containers:まだコンテナを起動していないため、このフィールドは空です。
  • Options:ブリッジネットワークのさまざまな設定オプションです。例えば、enable_icc が "true" の場合、このネットワーク上でのコンテナ間通信(Inter-Container Communication)が許可されていることを意味します。

これらの情報を理解することは、ネットワークトラブルシューティングや、特定の IP 範囲と通信するようにコンテナを構成する必要がある場合に非常に重要です。

カスタムブリッジネットワークの作成

デフォルトのブリッジネットワークは多くのユースケースに適していますが、カスタムネットワークを作成することで、より優れた分離と制御が可能になります。カスタムネットワークは、関連するコンテナをグループ化したり、どのコンテナ同士が通信できるかを制御したりする場合に特に便利です。

my-network という名前のカスタムブリッジネットワークを作成してみましょう。

docker network create --driver bridge my-network

このコマンドは新しいブリッジネットワークを作成します。bridge はデフォルトのドライバであるため、--driver bridge オプションは省略可能ですが、ここでは明示的に指定しています。

次に、新しいネットワークが作成されたことを確認します。

docker network ls

ネットワーク一覧に my-network が表示されるはずです。

NETWORK ID     NAME         DRIVER    SCOPE
1191cb61c989   bridge       bridge    local
91199fc6ad2e   host         host      local
47ac4e684a72   my-network   bridge    local
1078d2c781b6   none         null      local

リストに my-network が表示され、正常に作成されたことが確認できました。これで、コンテナをこのネットワークに接続できるようになりました。

コンテナをネットワークに接続する

カスタムネットワークが用意できたので、2 つのコンテナを作成して接続してみましょう。この例では、軽量な Web サーバーである nginx イメージを使用します。

次のコマンドを実行して、2 つのコンテナを作成します。

docker run -d --name container1 --network my-network nginx
docker run -d --name container2 --network my-network nginx

コマンドの各オプションの意味は以下の通りです:

  • -d:デタッチドモード(バックグラウンド)でコンテナを実行します。
  • --name:コンテナに名前を割り当て、後で参照しやすくします。
  • --network:コンテナが接続するネットワークを指定します。
  • nginx:コンテナの作成に使用するイメージ名です。

これらのコマンドにより、container1container2 という名前の 2 つのデタッチドコンテナが作成され、両方とも my-network に接続されます。

コンテナが実行中で、ネットワークに接続されていることを確認しましょう。

docker ps

このコマンドは実行中のすべてのコンテナをリストアップします。出力に両方のコンテナが表示されるはずです。

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
1234567890ab   nginx     "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds    80/tcp    container2
abcdef123456   nginx     "/docker-entrypoint.…"   20 seconds ago   Up 19 seconds   80/tcp    container1

この出力は、両方のコンテナが Nginx イメージを実行しており、コンテナ内部でポート 80 を公開していることを示しています。

コンテナ間通信のテスト

Docker ネットワークの主な利点の 1 つは、同じネットワーク上のコンテナが、コンテナ名をホスト名として使用して相互に通信できることです。これにより、IP アドレスを知らなくてもサービス間の通信を簡単に設定できます。

container1 から container2 にリクエストを送信して、これをテストしてみましょう。

docker exec container1 curl -s container2

コマンドの内訳は以下の通りです:

  • docker exec:実行中のコンテナ内でコマンドを実行するよう Docker に指示します。
  • container1:コマンドを実行したいコンテナの名前です。
  • curl -s container2:コンテナ内で実行するコマンドです。container2 に対して GET リクエストを送信し、-s フラグでサイレントモード(進捗を表示しない)にします。

このコマンドは container1 の内部で curl を実行し、container2 へリクエストを送ります。出力にデフォルトの Nginx 歓迎ページの HTML が表示されるはずです。

<!doctype html>
<html>
  <head>
    <title>Welcome to nginx!</title>
    <style>
      html {
        color-scheme: light dark;
      }
      body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
      }
    </style>
  </head>
  <body>
    <h1>Welcome to nginx!</h1>
    <p>
      If you see this page, the nginx web server is successfully installed and
      working. Further configuration is required.
    </p>

    <p>
      For online documentation and support please refer to
      <a href="http://nginx.org/">nginx.org</a>.<br />
      Commercial support is available at
      <a href="http://nginx.com/">nginx.com</a>.
    </p>

    <p><em>Thank you for using nginx.</em></p>
  </body>
</html>

このレスポンスが返ってくれば、container1 がコンテナ名を使用して container2 と通信できることが証明されます。Docker の組み込み DNS サーバーが、ネットワーク内のコンテナ名をその IP アドレスに解決しています。

コンテナポートの公開

デフォルトでは、カスタムネットワーク内のコンテナ同士は通信できますが、Docker ホストの外部からはアクセスできません。コンテナをホストや外部ネットワークからアクセス可能にするには、ポートを公開(エキスポーズ)する必要があります。

ポートを公開した新しいコンテナを作成してみましょう。

docker run -d --name exposed-container -p 8080:80 --network my-network nginx

コマンドの解説:

  • -d:デタッチドモードで実行。
  • --name exposed-container:コンテナ名を "exposed-container" に設定。
  • -p 8080:80:コンテナ内のポート 80 をホストのポート 8080 にマッピング。
  • --network my-network:カスタムネットワークに接続。
  • nginx:Nginx イメージを使用。

このコマンドは、exposed-container という名前の新しいコンテナを作成し、コンテナのポート 80 をホストのポート 8080 にマッピングして、my-network に接続します。

これで、ホストマシンから Web ブラウザで http://localhost:8080 にアクセスするか、curl を使用してこのコンテナの Nginx サーバーにアクセスできるようになります。

curl localhost:8080

先ほどと同じ Nginx の歓迎ページが表示されるはずです。今回は、別のコンテナからではなく、ホストから直接コンテナにアクセスしています。

ホストネットワークの使用

コンテナにホストのネットワークスタックを共有させたい場合は、ホスト(host)ネットワークドライバを使用できます。これにより、コンテナとホスト間のネットワーク分離が解除されます。これは特定のアプリケーションには有用ですが、ポートの競合が発生する可能性があるため、注意して使用する必要があります。

ホストネットワークを使用してコンテナを作成してみましょう。

docker run -d --name host-networked --network host nginx

このコマンドは、ホストネットワークを使用して host-networked という名前の新しいコンテナを作成します。ホストネットワークを使用する場合、コンテナはすでにホストのネットワークインターフェースを使用しているため、-p オプションによるポートマッピングは使用できないことに注意してください。

コンテナがホストネットワークを使用していることを確認するために、ネットワーク設定を調査します。

docker inspect --format '{{.HostConfig.NetworkMode}}' host-networked

このコマンドはコンテナを調査し、NetworkMode のみを表示するように出力をフォーマットします。host と出力されれば、コンテナがホストネットワークを使用していることが確認できます。

ホストネットワークを使用すると、コンテナはホストの IP アドレスを共有し、ホストのすべてのネットワークインターフェースに直接アクセスできます。これはパフォーマンスを最大化するのに役立ちますが、コンテナが使用するポートはホスト上で直接開かれるため、注意しないと競合が発生する可能性があります。

まとめ

この実験では、Docker ネットワークの基礎を学びました。さまざまなネットワークタイプ、カスタムネットワークの作成、コンテナの接続、コンテナ間通信のテスト、コンテナポートの公開、およびホストネットワークの使用について説明しました。これらの概念は Docker ネットワークの土台となるものであり、コンテナ化されたアプリケーションを設計・管理する上で不可欠です。

学んだ内容は以下の通りです:

  • Docker ネットワークの一覧表示と詳細調査
  • カスタムブリッジネットワークの作成
  • コンテナのネットワークへの接続
  • コンテナ間の通信テスト
  • コンテナポートのホストへの公開
  • コンテナでのホストネットワークの使用

これらのネットワーク概念を理解することで、より堅牢で安全なコンテナ化アプリケーションを設計できるようになります。Docker を使い続けるうちに、より高度なネットワークシナリオに遭遇することもありますが、ここで学んだ原則は、コンテナオーケストレーションやマイクロサービスアーキテクチャへの道のりにおいて、確かな基礎となるでしょう。

Docker ネットワークは、アプリケーションに隔離された環境を提供しつつ、コンテナ間や外部世界との制御された通信を可能にする強力なツールであることを忘れないでください。これらの概念を練習し、さらに高度なトピックを探索して、Docker ネットワークの管理に習熟していきましょう。