Dockerのネットワークの仕組みをちょっとだけ理解する
今回はDockerの基礎的な話です。
背景
踏み台サーバーを通して外部システムに接続をする必要がある機能をローカル環境で実装をしている際に、ローカルPC上では接続できるのにDocker上にあるアプリ経由だと接続ができない、といったことが起きました。
「そういえばアプリケーションはDocker上で動かしてるから、ホストで踏み台にアクセスしてもアプリケーション上では接続できないジャン( ◠‿◠ )」
ということは分かったのですが、なぜそうなるのかをうまく説明できるほど理解できていなかったので、改めて調べることにしました。
起きたこと
下記の手順を実行して、外部システムに接続できないということが起きました。
- ローカルホストで踏み台サーバー経由で外部システムに接続
-
ssh -NL 3000:external-system:80 bastion
- ブラウザで外部システムにアクセスできることを確認 -
http://127.0.0.1:3000/
にアクセス
-
- アプリケーション内で外部システムに接続
$this->connection = new Client(['base_uri' => 'http://127.0.0.1:3000/']);
アプリケーション内でのhttp://127.0.0.1
は、起動しているDockerコンテナ自身のサービスを指します。
そのため、http://127.0.0.1:3000/
では外部システムに接続することができませんでした。
Docker内のネットワークの状態
Dockerのネットワーク、基礎理解は万全ですか?【Dockerコンテナ・グレートジャーニー④】という記事が分かりやすかったので、以下画像をお借りします。
http://127.0.0.1:8080
でDocker上のサーバーにアクセスできる仕組みを解説しています。
Docker内でひとつのネットワークが作成されているようです。
Dockerには複数のネットワークが複数できるみたいなので、docker network ls
を実行して、どんなネットワークがあるかを見てみます。
NETWORK ID NAME DRIVER SCOPE
a450ae757a4e bridge bridge local
533460490ca7 host host local
cb9debf60dec none null local
5a410953ff96 my-app_default bridge local
開発しているアプリケーションは、my-app_defaultというネットワーク内で動いているようでした。
解決策
http://127.0.0.1
ではなく、http://host.docker.internal:3000/
で接続したら、外部システムに接続することができました!
ただしこれはあくまで開発環境向けであって、Docker Desktop forMac 以外の環境では動きません🙅♀️ので、ご注意を
補足
docker-composeでコンテナを作成した場合、networksセクションの記載がない場合は自動でネットワークを作成してくれます。
自動で作成された場合、ネットワークの名前は{docker-compose.ymlファイルが置かれているディレクトリ名}_default
になります。
感想
Dockerの理解が浅いので、いろいろ触って学んでいきたい気持ちがあったりなかったりします。
こちらの記事が分かりやすくてよかったです。
仮想化を知るには、仮想化ではないとは何かを知るべきだ【Dockerコンテナ・グレートジャーニー①】
Discussion