こんにちは、かつコーチです。
Webアプリケーションのコンテナと、データベースのコンテナを別々に起動して、いざ通信させようとしたら「繋がらない」と焦った経験はありませんか。
コンテナは互いに隔離された環境で動いているため、何もしなければ他のコンテナとやり取りできません。
この記事では、コンテナ同士を通信させるためのDockerネットワークの基本を、実際のコマンド例と一緒に解説します。
Dockerネットワークとは?
部屋同士をつなぐ内線電話に例えると
Dockerネットワーク(コンテナ同士が通信するための仮想的な通信網です)は、オフィスの内線電話に例えるとイメージしやすいです。
それぞれのコンテナは、防音壁で仕切られた個室のようなものです。
何も設定しなければ、隣の部屋にいるコンテナに話しかけることすらできません。
Dockerネットワークを作って複数のコンテナを同じネットワークに参加させることは、部屋同士に内線電話を引くようなものです。
内線電話があれば、部屋番号(コンテナ名)を指定するだけで、外部の電話回線を経由せずに直接やり取りできるようになります。
なぜコンテナ間通信の設定が必要か
Webアプリケーションとデータベースのように、複数のコンテナが連携して1つのシステムを構成するケースは非常に多いです。
Dockerはデフォルトでbridgeネットワーク(コンテナをホストとは別の仮想ネットワークに接続する仕組みです)を用意していますが、デフォルトのbridgeネットワークでは、コンテナ名による自動的な名前解決が行われません。
そのため、コンテナ同士を安定して連携させるには、自分でネットワークを作成し、参加させるコンテナを明示的に指定する必要があります。
基本の使い方
docker network createでネットワークを作る
まず、コンテナ間通信用のネットワークを作成します。
docker network create my-app-network
作成したネットワークの一覧は、以下のコマンドで確認できます。
docker network ls
–networkオプションでコンテナを接続する
作成したネットワークに、コンテナを参加させて起動します。
docker run -d \
--name my-db \
--network my-app-network \
-e MYSQL_ROOT_PASSWORD=example \
mysql:8.0
docker run -d \
--name my-web \
--network my-app-network \
-p 8080:80 \
my-web-app:1.0
--network my-app-network を両方のコンテナに付けることで、同じネットワーク内に配置されます。
コンテナ名で名前解決する
同じユーザー定義ネットワークに参加しているコンテナ同士は、コンテナ名をホスト名として名前解決できます。
例えば my-web コンテナのアプリケーションコードから、データベースの接続先を以下のように指定できます。
DB_HOST=my-db
DB_PORT=3306
IPアドレスを直接指定する必要がなく、コンテナ名(my-db)を指定するだけで通信相手を見つけられるのが、ユーザー定義ネットワークの大きなメリットです。
よくあるつまずきポイント・エラー対処
localhostで繋がらない
実際に私が最初にハマったのが、接続先のホスト名として localhost を指定してしまうミスです。
❌ Before:localhostを接続先に指定してしまう
DB_HOST=localhost
DB_PORT=3306
このように設定してアプリケーションコンテナを起動したところ、以下のようなエラーでデータベースに接続できませんでした。
Error: connect ECONNREFUSED 127.0.0.1:3306
コンテナ内から見た localhost は、あくまで「そのコンテナ自身」を指します。
Webアプリケーションのコンテナから見た localhost にMySQLは存在しないので、当然接続できません。
私はホストマシンでの開発に慣れていたせいで、つい localhost と書いてしまい、このエラーメッセージを見てようやく「コンテナごとにlocalhostの意味が違う」と理解しました。
✅ After:コンテナ名をホスト名として指定する
DB_HOST=my-db
DB_PORT=3306
同じユーザー定義ネットワークに参加していれば、コンテナ名がそのまま名前解決可能なホスト名になります。
接続確認は、片方のコンテナから docker exec で相手にpingを打つとわかりやすいです。
docker exec -it my-web ping my-db
応用・一歩先の使い方
bridge/host/noneネットワークドライバの違い
Dockerネットワークには、用途に応じて複数のドライバ(ネットワークの実装方式です)が用意されています。
| ドライバ | 特徴 | 主な用途 |
|---|---|---|
| bridge | コンテナ専用の仮想ネットワークを作る(デフォルト) | 単一ホスト内でのコンテナ間通信 |
| host | コンテナがホストのネットワークを直接共有する | ポート変換のオーバーヘッドを避けたい場合 |
| none | ネットワークインターフェースを持たない | 完全に隔離したい場合 |
普段の開発では、ユーザー定義の bridge ネットワークを作成する今回の方法が基本になります。
host や none は特殊な要件がある場合に検討する選択肢として、まずは名前だけ覚えておけば十分です。
まとめ
この記事のポイント
- Dockerネットワークは、コンテナ同士をつなぐ内線電話のような仕組み
docker network createでネットワークを作り、--networkオプションで参加させる- 同じユーザー定義ネットワーク内では、コンテナ名がそのままホスト名として名前解決できる
- コンテナ間通信では
localhostではなくコンテナ名を接続先に指定する
次に読むべき記事
- ボリュームでデータを永続化する
- docker-composeとは?複数コンテナをまとめて管理する
タグ: Docker, 中級者向け, ネットワーク