Docker ネットワークの深掘り

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

はじめに

この実験では、Docker ネットワークの基礎を踏まえ、さらに高度なネットワークの概念を探索します。主要な 3 つのネットワークモードである Bridge(ブリッジ)、Host(ホスト)、None(なし)について深く掘り下げます。また、カスタムネットワークの作成方法、異なるネットワーク間でのコンテナの接続方法、そして各ネットワークモードがコンテナ間の通信や分離にどのような影響を与えるかを理解します。この実習を通じて、Docker ネットワークの実践的な運用に関する強固な基礎を築くことができます。

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

Docker にはデフォルトのブリッジネットワークが用意されていますが、カスタムブリッジネットワークを作成することで、コンテナ間の通信をより適切に分離し、制御することができます。

  1. まず、現在の Docker ネットワークの一覧を確認しましょう。
docker network ls

以下のような出力が表示されるはずです。

NETWORK ID     NAME      DRIVER    SCOPE
296d1b460b17   bridge    bridge    local
91199fc6ad2e   host      host      local
1078d2c781b6   none      null      local
  1. 次に、カスタムブリッジネットワークを作成します。
docker network create my-custom-bridge
  1. 再度 Docker ネットワークを一覧表示して、作成されたことを確認します。
docker network ls

出力に my-custom-bridge が含まれているはずです。

NETWORK ID     NAME               DRIVER    SCOPE
296d1b460b17   bridge             bridge    local
91199fc6ad2e   host               host      local
7215f99d0080   my-custom-bridge   bridge    local
1078d2c781b6   none               null      local
  1. カスタムブリッジネットワーク上で 2 つのコンテナを起動し、ping をインストールします。
docker run --network=my-custom-bridge --name container1 -d nginx
docker run --network=my-custom-bridge --name container2 -d nginx

次に、両方のコンテナに ping ユーティリティをインストールします。デフォルトの Nginx イメージには ping が含まれていないため、この操作が必要です。

docker exec container1 apt-get update && docker exec container1 apt-get install -y iputils-ping
docker exec container2 apt-get update && docker exec container2 apt-get install -y iputils-ping
  1. コンテナ間の通信をテストします。
docker exec container1 ping -c 4 container2

ping の応答が正常に返ってくるはずです。これは、同じカスタムブリッジネットワーク上のコンテナが、コンテナ名を使用して通信できることを示しています。これは、Docker に組み込まれた DNS が、同じネットワーク内のコンテナ名を IP アドレスに解決するためです。

もし ping が成功しない場合は、両方のコンテナが実行中であること(docker ps で確認)と、ping ユーティリティが正しくインストールされていることを確認してください。

ネットワークを跨いだコンテナの接続

Docker では、1 つのコンテナを複数のネットワークに接続できるため、異なるネットワークに属するコンテナ間での通信が可能になります。これは、特定のコンテナを分離しつつ、特定の通信だけを許可したい場合に非常に便利です。

  1. まず、2 つ目のカスタムブリッジネットワークを作成します。
docker network create my-second-bridge
  1. ネットワークの作成を確認します。
docker network ls

これで、両方のカスタムネットワークが表示されるようになります。

NETWORK ID     NAME               DRIVER    SCOPE
296d1b460b17   bridge             bridge    local
91199fc6ad2e   host               host      local
7215f99d0080   my-custom-bridge   bridge    local
8a15f99d0081   my-second-bridge   bridge    local
1078d2c781b6   none               null      local
  1. container2 を新しいネットワークに接続します。
docker network connect my-second-bridge container2

このコマンドにより、container2my-custom-bridge に接続されたまま、my-second-bridge ネットワークにも追加されます。

  1. 2 つ目のネットワーク上に新しいコンテナを作成します。
docker run --network=my-second-bridge --name container3 -d nginx
docker exec container3 apt-get update && docker exec container3 apt-get install -y iputils-ping
  1. すべてのコンテナ間の通信をテストします。
docker exec container1 ping -c 2 container2
docker exec container1 ping -c 2 container3
docker exec container2 ping -c 2 container3

結果に注目してください:

  • container1container2 と通信できます(同じネットワークに属しているため)。
  • container1container3 と通信できません(異なるネットワークに属しているため)。
  • container2container1container3 の両方と通信できます(両方のネットワークに接続されているため)。

もし container1container3 に ping を通せてしまう場合は、ネットワークの分離設定に問題がある可能性があります。

ホストネットワークモード

ホストネットワークモード(Host network mode)は、コンテナと Docker ホスト間のネットワーク分離を取り除き、コンテナがホストのネットワークを直接使用できるようにします。これによりパフォーマンスを最大化できますが、分離レベルが下がるため、セキュリティ上の考慮が必要になります。

  1. ホストネットワークモードを使用してコンテナを作成します。
docker run --network host --name host-container -d nginx
  1. 現在のネットワークリストを確認します。
docker network ls

このコンテナはホストのネットワークを直接使用しているため、新しいネットワークは作成されません。

  1. コンテナがホストネットワークを使用していることを確認します。
docker inspect --format '{{.HostConfig.NetworkMode}}' host-container

出力は host となるはずです。

  1. ホストマシンから Nginx のデフォルトページにアクセスしてみます。
curl localhost:80

Nginx のウェルカムページが表示されるはずです。これは、コンテナがホストのネットワークを使用しており、Nginx がホストのネットワークインターフェースのポート 80 でリッスンしているために機能します。

注意:ホストマシンのポート 80 ですでに別のサービスが稼働している場合、このステップは失敗する可能性があります。その場合は、既存のサービスを先に停止する必要があります。

None ネットワークモード

'none' ネットワークモードは、ネットワークインターフェースを持たないコンテナを作成し、ネットワークから完全に分離します。これは最大限のセキュリティ分離が必要な場合に役立ちますが、コンテナはネットワーク経由で一切通信できなくなります。

  1. ネットワークなしでコンテナを作成します。
docker run --network none --name isolated-container -d alpine sleep infinity
  1. 現在のネットワークリストを確認します。
docker network ls

このコンテナはいかなるネットワークにも接続されていないため、新しいネットワークは表示されません。

  1. コンテナにネットワークインターフェースがないことを確認します。
docker exec isolated-container ip addr

ループバックインターフェース(lo)のみが表示されるはずです。eth0 やその他のネットワークインターフェースは存在しません。

  1. 分離されたコンテナから Google に ping を試みます。
docker exec isolated-container ping -c 2 google.com

コンテナにネットワークアクセス権がないため、"Network is unreachable"(ネットワークに到達できません)というエラーで失敗するはずです。

ネットワークエイリアスとサービスディスカバリ

Docker ネットワークは、ネットワークエイリアスを使用したサービスディスカバリ(サービス検出)をサポートしています。これは、回復力(レジリエンス)が高くスケーラブルなアプリケーションを作成する際に役立ちます。この機能により、複数のコンテナが同じ DNS 名に応答できるようになり、基本的なロードバランシングが可能になります。

  1. この演習用に新しいブリッジネットワークを作成します。
docker network create service-network
  1. ネットワークの作成を確認します。
docker network ls

リストに service-network が表示されているはずです。

  1. 同じネットワークエイリアスを持つ 2 つのコンテナを作成します。
docker run -d --network service-network --network-alias myservice --name service1 nginx
docker run -d --network service-network --network-alias myservice --name service2 nginx
  1. クライアントコンテナを作成し、nslookup を使用してサービスを解決します。
docker run --rm --network service-network appropriate/curl nslookup myservice

両方のコンテナの IP アドレスが返されるはずです。これは、Docker の組み込み DNS サーバーが 2 つのコンテナ間でロードバランシングを行っていることを示しています。

  1. サービスへのアクセスを複数回テストします。
for i in {1..4}; do docker run --rm --network service-network appropriate/curl ping -c 1 myservice; done

両方のコンテナから応答があるはずで、基本的なロードバランシングが行われていることがわかります。Docker DNS サーバーは、myservice を解決する際に 2 つの IP アドレスを交互に返します。

PING myservice (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.106 ms

--- myservice ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.106/0.106/0.106 ms
PING myservice (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.119 ms

--- myservice ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.119/0.119/0.119 ms
PING myservice (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.097 ms

--- myservice ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.097/0.097/0.097 ms
PING myservice (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.140 ms

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

まとめ

この高度な Docker ネットワーク実験では、いくつかの重要な概念を学びました。

  1. コンテナの分離と通信を改善するためのカスタムブリッジネットワーク
  2. 複数のネットワークを跨いだコンテナの接続
  3. ホストのネットワークスタックに直接アクセスするためのホストネットワークモード
  4. 完全なネットワーク分離のための None ネットワークモード
  5. スケーラブルなアプリケーションを構築するためのネットワークエイリアスとサービスディスカバリ

Docker のこれらの高度なネットワーク機能は、コンテナ間の通信と分離を精密に制御しながら、複雑なマルチコンテナアプリケーションを設計するための強力なツールを提供します。これらの概念を理解することは、効率的で安全、かつスケーラブルなコンテナ化アプリケーションを設計する上で不可欠です。

Docker ネットワークは高い柔軟性を提供しますが、コンテナネットワークアーキテクチャを設計する際には、セキュリティへの影響を考慮することが重要です。常に「最小権限の原則」に従い、必要なポートとサービスのみを公開するようにしてください。

Docker の利用を続ける中で、これらのネットワーク概念は、複雑なアプリケーションやマイクロサービスアーキテクチャをオーケストレーションする際に非常に役立つでしょう。定期的にこれらの概念を練習し、Docker ネットワークを効果的に管理できるようになりましょう。