ブリッジネットワークの利用

読む時間の目安: 2 分

ネットワーク技術において、ブリッジネットワークとはリンク層のデバイスのことであり、ネットワークセグメントに向けてトラフィックを送信します。 ブリッジはハードウェアデバイス、ソフトウェアデバイスのいずれも可能であり、ホストマシンのカーネル内で動作します。

Docker の用語におけるブリッジネットワークは、同一のブリッジネットワークに接続されたコンテナーが、互いに通信を行うためのソフトウェアブリッジを利用します。 そしてそのブリッジネットワークに接続していないコンテナーからは隔離されます。 ホストマシン内には Docker ブリッジドライバーのルールが自動的にインストールされます。 このルールにより、別のブリッジネットワーク上のコンテナーは、直接通信することはできなくなります。

ブリッジネットワークは、同一 の Docker デーモンホスト上に稼動しているコンテナーに適用されます。 別の Docker デーモンホスト上に稼動するコンテナーとの間で通信を行うためには、OS レベルでのネットワーク管理を行うか、あるいは オーバーレイネットワーク を利用します。

Docker を起動すると デフォルトブリッジネットワーク(または単にブリッジ)が自動的に生成されます。 そして特に指定がない限り、この後に生成されるコンテナーは、このネットワークに接続されます。 もちろんユーザー定義によるカスタムブリッジネットワークを生成することもできます。 ユーザー定義によるブリッジネットワークは、デフォルトのブリッジネットワークよりも優先されます。

ユーザー定義ブリッジとデフォルトブリッジの違い

  • ユーザー定義ブリッジは、コンテナー間において自動的に DNS 解決を提供します。

    デフォルトブリッジネットワーク上にあるコンテナーは、IP アドレスによって互いにアクセスすることができます。 ただしこれは --linkオプション を使った場合であり、古い機能とされています。 ユーザー定義のブリッジネットワークにおいて、コンテナーは名前またはエイリアスにより互いを識別します。

    今、フロントエンドにウェブ、バックエンドにデータベースを持つアプリケーションがあるとします。 コンテナーをそれぞれwebdbとすると、web コンテナーから db コンテナーはdbとして接続します。 そのアプリケーションスタックがどの Docker ホスト上で動作していても同様です。

    上と同じアプリケーションスタックを、デフォルトブリッジネットワーク上において実行したとします。 その場合は(古い--linkフラグを使い)コンテナー間に手動でリンクを生成する必要があります。 このリンクは双方向に生成しなければなりません。 したがって通信すべきコンテナーが 2 つ以上になってくると、このやり方は面倒なものに思うかもしれません。 それならコンテナーすべてに/etc/hostsを設定する方法もありますが、今度はデバッグがしづらくなるという問題が発生します。

  • ユーザー定義ブリッジ上のコンテナーは、さらに隔離されます。

    --networkの指定を一切行わなければ、すべてのコンテナーがデフォルトブリッジネットワークに接続されます。 これにはリスクがあります。 無関係なスタック、サービス、コンテナーが通信できてしまうからです。

    ユーザー定義ネットワークを使うとネットワーク範囲が限定され、そのネットワークに接続しているコンテナーだけが、互いに通信を行うことができます。

  • ユーザー定義ネットワークであれば、コンテナーの動作中にアタッチ、デタッチを行うことができます。

    コンテナーの稼働中であれば、ユーザー定義ネットワークとの接続や切断は、その場ですぐに行うことができます。 一方デフォルトブリッジネットワークの場合、コンテナーをネットワークから切り離すには、コンテナーを停止させ、別のネットワークオプションを使ってコンテナーを再生成しなければなりません。

  • ユーザー定義ネットワークは、設定変更可能なブリッジを生成します。

    デフォルトブリッジネットワークを利用している場合に、ネットワーク設定を変更することはできますが、MTU やiptablesルールといった設定は全コンテナーに適用されることになります。 さらにデフォルトブリッジネットワークの設定変更は Docker 外部で処理されるため、Docker デーモンの再起動が必要になります。

    ユーザー定義ブリッジネットワークはdocker network createを使って生成され設定されます。 アプリケーションがグループ分けされていて、ネットワーク要件が異なっているとします。 ユーザー定義ブリッジは、個々に設定を変えて生成することができます。

  • デフォルトブリッジネットワーク上のリンクコンテナーは、環境変数を共有します。

    もともと 2 つのコンテナー間で環境変数を共有するには、--linkフラグ を使って互いをリンクするのが唯一の方法でした。 この変数共有は、ユーザー定義ネットワークでは利用できません。 ただし変数共有を行う優れた方法はあります。 以下がその考え方です。

    • 複数コンテナーからはファイルやディレクトリをマウントすることができます。 これには Docker ボリュームを利用します。 そしてそこに共有したい情報を含めます。

    • 複数コンテナーはdocker-composeを利用して同時に起動することができます。 その compose ファイルには共有変数を定義することができます。

    • スタンドアロンなコンテナーではなく swarm サービスを利用することができます。 これにより共有化した secretsconfigs を利用することができます。

同一のユーザー定義ブリッジネットワークに接続するコンテナーは、効率性により全ポートが互いに公開されます。 コンテナーへの接続ポート、あるいは別のネットワーク上の Docker でないホストへの接続ポートは、公開されている 必要があり、-pまたは--publishを指定します。

ユーザー定義ブリッジの管理

ユーザー定義ブリッジネットワークを生成するには、コマンドdocker network createを実行します。

$ docker network create my-net

サブネット、IP アドレス範囲、ゲートウェイ、その他のオプションを指定することもできます。 詳しくは docker network create リファレンスを参照してください。 あるいはdocker network create --helpの出力を確認してください。

docker network rmコマンドを使うと、ユーザー定義のブリッジネットワークを削除することができます。 コンテナーがその時点でネットワークに接続しているのであれば、その前に 接続を切って ください。

$ docker network rm my-net

実際には何が起きるか

ユーザー定義ブリッジの生成、削除を行う場合、あるいはユーザー定義ブリッジとコンテナーを接続する、または接続を切る場合、Docker はオペレーティングシステムに固有のツールを使って、用いられているネットワークインフラストラクチャー(ブリッジデバイスの加除や Linux 上のiptablesの設定など)を制御します。 この動作は実装の詳細を考慮して処理されるべきであるため、ユーザー定義ネットワークの管理は Docker の動作に従ってください。

ユーザー定義ブリッジへのコンテナーの接続

新たにコンテナーを生成するときは、--networkフラグを複数指定することができます。 以下の例では Nginx コンテナーをmy-netネットワークに接続しています。 またコンテナーのポート 80 を Docker ホストのポート 8080 に公開しています。 外部のクライアントプログラムは、このポートからアクセスすることができます。 my-netネットワークに別のコンテナーが接続していたら、my-nginxコンテナー上のポートすべてにアクセスすることができます。元のコンテナーからも同じことが言えます。

$ docker create --name my-nginx \
  --network my-net \
  --publish 8080:80 \
  nginx:latest

実行中 のコンテナーを既存のユーザー定義ブリッジに接続するにはdocker network connectコマンドを使います。 以下に示すコマンドは、すでに実行されているmy-nginxコンテナーを、既存のmy-netネットワークに接続します。

$ docker network connect my-net my-nginx

ユーザー定義ブリッジからのコンテナーの接続解除

ユーザー定義ブリッジから実行コンテナーの接続を解除するにはdocker network disconnectコマンドを使います。 以下に示すコマンドは、my-nginxコンテナーをmy-netネットワークから切り離します。

$ docker network disconnect my-net my-nginx

IPv6 の利用

Docker コンテナーが IPv6 をサポートする必要がある場合は、Docker デーモンにおいて オプションを有効 にして、設定を再読み込みする必要があります。 ただしそれを行うには、あらかじめ IPv6 ネットワークを構築しておき、コンテナーに対して IPv6 アドレスを割り当てておくことが必要です。

ネットワークを構築する際に--ipv6フラグを指定すれば IPv6 を有効にすることができます。 なおデフォルトのbridgeネットワークにおいては、IPv6 サポートを無効にすることはできません。

Docker コンテナーからの外部フォワード有効化

デフォルトブリッジネットワークに接続されているコンテナーからのトラフィックは、デフォルトでは外部にフォワード されません。 フォワードを有効にするには、設定変更が 2 つ必要です。 それは Docker コマンドで行うものではなく、Docker ホストのカーネルを変更するものです。

  1. Linux カーネルにおいて IP フォワーディングを有効に設定します。

    $ sysctl net.ipv4.conf.all.forwarding=1
    
  2. iptablesFORWARDポリシーをDROPからACCEPTに変更します。

    $ sudo iptables -P FORWARD ACCEPT
    

上で行ったことは、再起動後には設定が失われます。 そこで起動スクリプトにその設定を加えることにします。

デフォルトのブリッジネットワークの利用

デフォルトのbridgeネットワークは Docker の古い機能の一部に過ぎないので、本番環境での利用はお勧めできません。 これは手動で設定するものになっていて、技術的な欠点 があります。

デフォルトブリッジネットワークへのコンテナーの接続

--networkフラグを指定しなかった場合で、ネットワークドライバーの指定を行った場合、デフォルトでコンテナーは、デフォルト のbridgeネットワークに接続されます。 デフォルトbridgeネットワークに接続されたコンテナーは通信が可能ですが、かつての--linkフラグ を利用しない限りは、互いに IP アドレスを使ってしか通信はできません。

デフォルトブリッジネットワークの設定

デフォルトbridgeネットワークを設定するには、daemon.json内においてオプションを指定します。 以下はdaemon.jsonにおいてオプションをいくつか指定した例です。 オプション指定は、設定変更を行いたいもののみ記述してください。

{
  "bip": "192.168.1.1/24",
  "fixed-cidr": "192.168.1.0/25",
  "fixed-cidr-v6": "2001:db8::/64",
  "mtu": 1500,
  "default-gateway": "192.168.1.254",
  "default-gateway-v6": "2001:db8:abcd::89",
  "dns": ["10.20.1.2","10.20.1.3"]
}

設定変更を有効にするため Docker を再起動します。

デフォルトブリッジネットワークにおける IPv6 の利用

Docker において IPv6(IPv6 の利用 参照)のサポートを設定すると、デフォルトブリッジネットワークも IPv6 に対応するように自動的に設定されます。 ユーザー定義ブリッジとは違って、デフォルトブリッジにおいては IPv6 を無効にすることはできません。

次のステップ

network, bridge, user-defined, standalone