Laravel Sail からホスト側のサーバーにアクセスする方法
こんにちは。 SAW です。
最近、学習の一環として 英語のブログを書き始めました。
公開前する前に ChatGPT に文章を添削してもらっているので、より自然な表現を身につけられたら良いなと思います。
Laravel Sail で起動したコンテナから、 ホスト側の別サーバーにアクセスしようとしたところ、 サーバーに到達できずエラーが発生する という問題に遭遇しました。
本記事では、 Laravel Sail のコンテナからホスト側のサーバーにアクセスする方法 を紹介します。
なお、本記事では Laravel のバージョンが 12.x 系を前提としています。
対象読者
本記事で想定する読者層は以下の通りです。
- Laravel について基本的な知識を有している
- Docker について基本的な知識を有している
エラーの内容
以下のコードを、 localhost:8000 で動いている Laravel のサーバーで実行した場合を想定します。
なお、 localhost:8001 は別の Laravel プロジェクトで、別のコンテナ上で稼働している想定です。
$url = 'http://localhost:8001/';
$response = Http::get($url);
このコードを実行すると、以下のようなエラーが表示されました。
cURL error 7: Failed to connect to localhost port 8001 after 0 ms:
Couldn't connect to server (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)
for http://localhost:8001/
ホスト側からは localhost:8000 と localhost:8001 の両方とも HTTP 通信ができていたので、 Docker コンテナから localhost:8001 と指定してもホスト側のサーバーには通信できないようです。
解決方法
リクエスト先の URL で localhost の部分を host.docker.internal に書き換えることで HTTP リクエストが正常に通るようになりました。
- $url = 'http://localhost:8001/';
+ $url = 'http://host.docker.internal:8001/';
$response = Http::get($url);
同様に、データベースを Laravel Sail で作成されるコンテナではなく、ホストマシン上で動作する DB サーバーに接続したい場合は、.env の DB_HOST の値に host.docker.internal を指定します。
DB_HOST=host.docker.internal
補足: host.docker.internal について
Laravel Sail のコンテナを起動するための docker-compose.yml には、 extra_hosts に以下の定義が含まれています。
extra_hosts:
- 'host.docker.internal:host-gateway'
extra_hosts はホスト名と IP アドレスをマッピングする設定です。
この例では、 host.docker.internal が host-gateway に解決されます。
host-gateway はホスト側の IP アドレスを自動的に解決してくれる特殊な値です。
そのため、Laravel Sail のコンテナ内から host.docker.internal を指定すると、ホスト側のサーバーへ通信できるようになります。
Docker 公式ドキュメントでは次のように説明されています。
The
--add-hostflag supports a specialhost-gatewayvalue that resolves to the internal IP address of the host. This is useful when you want containers to connect to services running on the host machine.
また、 host.docker.internal というホスト名は Docker Desktop が自動的に host-gateway を解決していたため、慣習的に利用されています。
It's conventional to use
host.docker.internalas the hostname referring tohost-gateway. Docker Desktop automatically resolves this hostname, see Explore networking features.
※ Linux 環境では Docker のバージョンによっては動作しない場合があります。
まとめ
本記事のまとめは以下の通りです。
- Laravel Sail のコンテナからホスト側のサーバーにアクセスする方法を紹介
- ホスト名に
host.docker.internalを指定
- ホスト名に
Docker のネットワークまわりの設定って難しいなと、改めて思いました (笑)
参考文献
Discussion