🐧 Linux 総合学習プラットフォーム
コンテナ Docker/Podman ・ 中級

コンテナのネットワーク

複数のコンテナを連携させるとき、コンテナ同士はどうやって相手を見つけて通信するのでしょうか。Dockerは既定でbridgeという仮想ネットワークを用意しますが、実務ではユーザ定義ネットワークを作り、コンテナ名で名前解決させるのが定石です。ここではコンテナ間通信の仕組みと、外部公開のためのポートマッピングとの違いを整理し、Composeが裏で何をしているのかも見ていきます。

複数のコンテナを組にして動かせるようになると、次に必ずつまずくのがネットワークだ。webコンテナからdbコンテナへ、どうやってつなげばいいのか。

ここでIPアドレスを直接書いてしまうと、コンテナを作り直すたびにIPが変わって動かなくなる。実務ではIPを直書きせず、コンテナ名やサービス名で相手を呼べる仕組みを使う。

つまずきコンテナのIPアドレスは再作成のたびに変わりうる。設定にIPを直書きするのは事故のもとだ。

🌉 既定のbridgeネットワーク

Dockerをインストールすると、既定でbridgeという名前の仮想ネットワークが1つ用意される。docker runで特に指定せずにコンテナを起動すると、このbridgeネットワークに接続される。

bridgeネットワークに参加したコンテナは、ホストとは独立した仮想のネットワーク空間の中でIPアドレスを1つずつ割り当てられる。コンテナ同士はこのネットワークを介して通信できるが、既定のbridgeには弱点がある。名前解決の機能が限定的で、コンテナ名を指定しても相手を見つけられないことが多い。

🔗
たとえ既定のbridgeは、名札を付けていない人だけが集まった部屋のようなものだ。同じ部屋にはいるが、名前で呼んでも誰も反応してくれない。
既定のbridgewebdb名前では届かないユーザ定義netweb → db名前で通信OKnetwork create

🏷️ ユーザ定義ネットワークと名前解決

この弱点を解消するのが、docker network createで自分で作るユーザ定義ネットワークだ。ユーザ定義ネットワークに参加したコンテナ同士は、コンテナ名(または--nameで付けた名前)をそのままホスト名として使い、お互いを見つけられる。

ユーザ定義ネットワーク app-netwebconnect(db:5432)db名前で見つかる名前解決OK
💡
ポイントユーザ定義ネットワークに参加していれば、webコンテナはdbのIPアドレスを知らなくても、単に「db」というホスト名で接続先を指定できる。IPを気にする必要がなくなる。
手順の例。$ docker network create app-net でネットワークを作成し、$ docker run --network app-net --name db postgres:16 、$ docker run --network app-net --name web myapp のように同じネットワーク名を指定して起動する。web側のアプリはdbという名前で接続先を書ける。

🔌 コンテナ間通信とポート公開の関係

ここで整理しておきたいのが、コンテナ間の通信と、ホストへの公開(-pオプション)の違いだ。同じネットワークに参加しているコンテナ同士は、-pでポートを公開していなくても、コンテナが持つポート番号に直接アクセスできる。

-pオプションは、あくまで「ホストの外側からコンテナの中へ」アクセスするための穴を開けるものだ。コンテナ同士の内側の会話には、この穴は関係ない。

💡
ポイント内側同士(コンテナ間)の通信にポート公開は不要。外側(ホストや外部)からアクセスさせたいときだけ-pで穴を開ける。dbコンテナは多くの場合、外部に公開せずネットワーク内だけで閉じておくのが安全だ。
コツデータベースのコンテナは-pで公開しないのが基本だ。アプリコンテナからはネットワーク越しに名前で届くので、外部への公開ポートは最小限にとどめるとよい。

🔍 ネットワークを覗く——ls・inspect

いま存在するネットワークの一覧はdocker network lsで確認できる。既定で用意されているbridge・host・noneに加え、自分で作ったネットワークがここに並ぶ。

特定のネットワークの詳細、つまりどのコンテナが参加していて、それぞれどんなIPを持っているかは、docker network inspect ネットワーク名で確認できる。トラブルシューティングのときによく使うコマンドだ。

$ docker network ls でネットワーク一覧を確認し、気になるネットワークがあれば $ docker network inspect app-net で参加コンテナとIPアドレスの詳細を見る。
つまずき「webからdbに繋がらない」というトラブルの多くは、実は2つのコンテナが同じネットワークに参加していないことが原因だ。まずdocker network inspectで両方が同じネットワークに載っているかを確認する癖をつけると原因切り分けが早い。
コツdocker run時にネットワーク名を指定し忘れると既定のbridgeに入ってしまう。--networkの指定漏れは名前解決トラブルの定番なので、起動コマンドを見直すときはまずここを疑うとよい。

🧩 composeは自動でネットワークを作る

前のトピックで扱ったDocker Composeは、実はこのユーザ定義ネットワークの仕組みを裏側で自動的に使っている。compose.yamlでservicesを定義してdocker compose upすると、Composeはそのプロジェクト専用のネットワークを自動生成し、全サービスをそこに参加させる。

だからこそ、compose.yamlの中でサービス名(web・dbなど)をそのままホスト名として書くだけで通信できていたわけだ。裏では毎回docker network createと同じことが自動で行われている。

🔗
たとえdocker network createを手作業でやるのが「自分で名簿を用意して部屋に貼る」やり方だとすれば、Composeは「部屋に入るだけで自動的に名簿に名前が載る」やり方だ。手間が省ける分、裏で何が起きているかを知っておくと迷わない。

コンテナ同士が名前で会話できる仕組みが分かったところで、次は作ったイメージを他の場所へ届ける方法、レジストリとタグの話に進もう。

この項目に出てくる用語

bridgeネットワークぶりっじねっとわーく
Dockerが既定で用意する仮想ネットワーク。特に指定せず起動したコンテナが参加する。
ユーザ定義ネットワークゆーざていぎねっとわーく
docker network createで自分で作る仮想ネットワーク。参加コンテナ同士はコンテナ名で通信できる。

関連コマンド

docker network

▶ 学習アプリでこの続きを学ぶ・演習する