君もDockerコンテナ間で通信する方法に悩んでいないかい?
以前、コンテナ内のhost.docker.internalはホストPCのlocalhostと読み換えられるよ!という話をしていました ↓
しかしあれから
Dev Container上の開発環境から、別コンテナのSQLサーバーにアクセスできない!
という問題が度々発生してしまい頭をかかえることに
公式ドキュメントや技術ブログを色々と漁った挙句、どうやら
Dockerコンテナ内から別コンテナにアクセスする場合はDocker Networkを使用したほうがよろしい
らしく、
実際にコンテナ間接続の再現性が高い方法だったのでざっくり解説します
Docker Networkとは何?
簡単に言うと
複数のコンテナを同じネットワーク内で利用出来るようにする機能
例えば
- コンテナA (クライアント用)
- コンテナB (サーバー用)
がある場合、
コンテナAからコンテナB内のポート3000番に接続する際には
http://[コンテナBの名前]:3000
と指定するだけで接続ができるというもの
便利ですね。
設定方法
今回はbridgeドライバを用いたDockerネットワークの設定を解説します
公式ドキュメントでは
- docker-composeを用いる方法
- コンテナそのもののネットワークとホストを同一化する方法
など他にも様々な方法が紹介されていますが、単純に複数のコンテナを繋げる用途であればこの設定で十分です
bridgeドライバが何かというと、つまり
コンテナAとコンテナBのネットワークの橋渡し
をうまいことやってくれるドライバ(文字通り)
設定の手順としては
-
Docker Networkを作成
-
コンテナAをNetworkに追加
-
コンテナBをNetworkに追加
を順番に行います
1 の「ネットワークを作成する作業」については次のコマンド
docker network create ネットワーク名 -d ドライバの種類
2, 3 で行う「ネットワークにコンテナを接続する作業」は次のコマンドで実現できます
docker network connect 1で作成したネットワーク名 接続したいコンテナ名
したがって最終的なコマンドは以下のとおり
$ docker network create my-net -d bridge
$ docker network connect my-net コンテナAの名前
$ docker network connect my-net コンテナBの名前
上手く設定できていれば、コンテナAから
http://[コンテナBの名前]:[ポート番号]
へ接続できるようになっているはず
(ポート番号はホスト側ではなく、コンテナB内側なので注意)
なぜhost.docker.internalが動かないケースがあったのか?
不明です なぜでしょう
別コンテナのサーバーに繋がるケースもあれば、その逆も然り。
再現性が無く調査を諦めました。
(原因がわかる方は是非ともコメントで教えていただけると大変助かります)
ひとまず
-
Docker Networkでは安定して接続できていること
-
開発用途であればあまり困らないこと
から、これからはDocker Networkを優先しようかなと思った次第です。
Dev Containerで環境構築コストがだいぶ下がっているので、せっかくならDocker Networkも自動化しておきたいですね
参考資料