Dockerとコンテナ技術 その8:ネットワーク

コンテナは一つのシステム内で、その用途ごとに分けて複数作成するのが一般的です。
例えばWebサーバーのコンテナとDBサーバーのコンテナを作成する、といった感じです。
コンテナは独立した仮想環境であるため、ネットワークで繋ぐ必要があります。
今回の記事では、コンテナの周りのネットワークについてまとめていきます。

Dockerのネットワークモード

Dockerではコンテナを作成する際に3種類のネットワークモードが提供されています。
bridgeとhostとnoneです。

bridgeネットワーク

概要

bridgeネットワークは、Dockerがデフォルトで作成する仮想ネットワークです。
このネットワークは、コンテナがホストマシンのネットワークを通じて外部と通信するために使用されます。
Dockerでネットワークを扱う場合、bridgeネットワークを利用することが多いです。

特徴

  • コンテナは同じブリッジネットワーク上で互いに通信できます。
  • コンテナはNAT (Network Address Translation) を使用して外部ネットワークと通信します。
  • ホストマシンの特定のポートをコンテナのポートにマッピングすることができます。

利用例

compose.yamlに以下のように記述することでmy-bridge-networkというbridgeネットワークを作成することができ、webコンテナはこのネットワークを通じて外部や他のコンテナと繋がりを持つことができます。

version: '3.8'

services:
  web:
    image: nginx
    networks:
      - my-bridge-network

networks:
  my-bridge-network:
    driver: bridge

hostネットワーク

概要

hostネットワークは、コンテナがホストマシンのネットワークスタックを直接使用するネットワークモードです。
これにより、コンテナはホストと同じネットワークインターフェースを共有します。

特徴

  • コンテナはホストと同じネットワークインターフェースを共有します。
  • ポートマッピングが不要になります。
  • ネットワーク性能が向上する場合があります。

利用例

compose.yamlに以下のように記述します。
webコンテナはホストOSと同じネットワークインターフェースを利用できるようになります。

version: '3.8'

services:
  web:
    image: nginx
    network_mode: host

noneネットワーク

概要

noneネットワークは、コンテナにネットワーク接続を提供しないモードです。
このモードでは、コンテナはネットワークインターフェースを持たず、外部と通信できません。

特徴

  • コンテナはネットワークインターフェースを持ちません。
  • 完全に隔離された環境を提供します。

利用例

以下のようにcompose.yamlを記述することで完全に隔離されたコンテナを作成することができます。

version: '3.8'

services:
  myservice:
    image: nginx
    network_mode: "none"

ポートマッピングによる外部との通信

ポートマッピングとはホストの特定のポート番号をコンテナにマッピングすることです。
ポートマッピングすることによって、ホストの特定のポートへのアクセスによってコンテナにアクセスすることができるようになります。
コンテナを外部に公開する場合、ポートマッピングを行う必要があります。
以下のポートマッピングの例を示します。

version: '3.8'

services:
  web:
    image: nginx
    ports:
      - "8080:80"

ports: - "8080:80"と記述されている箇所で、ホストのポート番号8080をコンテナのポート番号80にマッピングしています。

カスタムネットワークによるアクセス制御の例

最後にWebサーバーとDBサーバーからなる簡単な構造のシステムでアクセス制御を行う例を見てみます。
Webサーバーは外部に公開し、DBサーバーは外部には公開せずWebサーバーからのみアクセスを行います。
このアクセス制御を行うために、カスタムネットワークを作成していきます。
compose.yamlに下記のように記述することでこれらを実現できます。

version: '3.8'

services:
  web:
    image: nginx
    ports:
      - "80:80"
    networks:
      - frontend
      - backend

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

少し詳しく見ていきましょう。
まず、networks:内に作成するfrontendbackendという2つのカスタムネットワークが記述されています。
この2つはどちらもコンテナ独自のネットワークのため、bridgeネットワークとして作成しています。
次に、Webサーバーのコンテナを見ていきます。
web:内にコンテナのネットワークに関する記述もされています。
ports: - "80:80"とすることで外部に公開し、networks:内に作成したカスタムネットワークを記述することでコンテナと紐づけています。
コンテナが複数のネットワークに接続している時は、外部への通信は単語順で1つめの非内部ネットワークを経由します。
そのため、frontendネットワークは外部にも公開するネットワークであり、backendネットワークは非公開のDBサーバーとの通信のみに利用するネットワークとなります。
最後に、DBサーバーのコンテナを見ていきます。
db:内の記述を見ていくと、こちらにもnetworks:が記載されていますが、こちらのコンテナでは外部に公開するネットワークのfrontendはありません。
backendネットワークのみ紐づいているため、外部に公開されることなくWebサーバーとのみ通信を行うことができます。

まとめ

  • Dockerにはbridge, host, noneの3つのネットワークモードがある。
  • bridgeネットワーク: デフォルトのネットワークモードで、コンテナ間の通信やホストとのポートマッピングが可能。
  • hostネットワーク: コンテナがホストのネットワークインターフェースを直接使用し、高速なネットワーク通信が可能。
  • noneネットワーク: ネットワークインターフェースを持たず、完全に隔離された環境を提供。
  • 外部に接続する場合はポートマッピングを行う。
  • コンテナは複数のネットワークに追加することができる。
  • 外部に接続されたコンテナは、compose.yamlで指定した1つ目のネットワークを介して外部と通信する。
  • カスタムネットワークを作成しネットワークの構成を柔軟に管理することができる。

コンテナはそれぞれ独立した環境であり、1つのシステムで複数のコンテナを作成することが多いので、ネットワークを理解することが重要です。
難しい概念ではありますが、基本的な部分をしっかりと押さえて適切に扱えるようにしていきましょう。
ここまで読んでいただき、ありがとうございました。
それでは、また。