環境
以下の環境で動作させています。
% sw_vers
ProductName: macOS
ProductVersion: 12.6.5
BuildVersion: 21G531
Docker
$ docker ps
CONTAINER ID IMAGE PORTS NAMES
// API呼び出し元
a1b2c3d4e5f6 private-registry-app.local:5000/docker/php-83:latest 0.0.0.0:xxxxx->80/tcp app1-cakephp
// ログインAPI提供
7g8h9i0j1k2l private-registry-api.local:5000/docker/php-83:latest 0.0.0.0:xxxxx->80/tcp api1-cakephp
設定ファイル内のApi.base_path
に外部APIのURLを指定することで、APIへリクエストを送信するようにしています
// config/app.php
'Api' => [
'base_path' => 'http://example.com/api',
'endpoints' => [
'login' => '/users/login',
],
],
ハマった事象
作成中のアプリケーションに、同社の別アプリケーションのログイン用APIを叩いてログイン処理を実装しようとしたらなかなかにハマってしまいました。
試したこと
1.そのままlocalhostを使ってみる
'Api' => [
'base_path' => 'http://localhost:XXXXX/api',
'endpoints' => [
'login' => '/users/login',
],
],
送信結果:❌️(接続失敗)
2025-06-24 18:50:38 error: ログインエラー Email: test@example.com, IP: 172.18.0.3, Message: cURL Error (7) Failed to connect to localhost port 57965 after 0 ms: Couldn't connect to server
2.host.docker.internal を使ってみる
host.docker.internal
とは、Docker Desktop for Mac/Windows
でコンテナからホストにアクセスするための特殊なDNS名のこと。
開発環境でしか使わないしいいのでは?とapi1-cakephp
のポート番号を使用して、コンテナからホストのサービスへのリクエストを試してみます。
が、、、
'Api' => [
'base_path' => 'http://host.docker.internal:XXXXX/api',
'endpoints' => [
'login' => '/users/login',
],
],
送信結果:❌️(DebugKitによるホスト制限により接続不可)
DebugKit is disabling itself as your host `host.docker.internal` is not in the known safe list of top-level-domains...
DebugKit
が host.docker.internal
を安全なTLDとみなさないため、自動的に無効になるというものです。
(※.internal
は一般に予約されており、「外部に公開されない内部向けアドレス」として使われるため)
このエラーの解決方法として調べたときに真っ先に上がってきたのが
「DebugKitを強制的に有効化する」 だったので、これは速攻で不採用にしました。(他への影響が計り知れない)
// config/bootstrap.php
Configure::write('DebugKit.forceEnable', true);
こんな具合でああでもないこうでもないとしていたのですが、
host.docker.internal
の直接使用が失敗したタイミングで上席の方に相談したところ、紹介してもらったのが ngrok というツールでした。
ngrok(エングロック)とは?
ローカルの開発環境を一時的にインターネットに公開できるトンネリング/リバース・プロキシツールで、
通常は localhost
でしか動かないアプリを、外部公開できるURLに変換可能できるとのこと。
アプリのプロトタイプの一時公開などに使用するそうです。素晴らしい〜
早速利用していきます。操作は以下の通り実施しました。
※サインアップやサインインの手順については割愛します。
※今回は認証トークンが取得できればよかったため、OSへのinstall(homebrew)は行いませんでした。
1. Getting Started - Your Authtoken
から認証トークンをコピー
2. ngrokでホスト上のポートを公開
以下のコマンドで、ホストの host.docker.internal:XXXXX をngrok経由で公開します。
docker run -it --rm \
-e NGROK_AUTHTOKEN=hogehogefugafugapiyopiyo \
ngrok/ngrok http host.docker.internal:XXXXX
公開成功〜
ngrok (Ctrl+C to quit)
🏃➡️ The Go SDK has reached v2—now simpler, more streamlined, and way more powerful: https://ngrok.com/r/go-sdk-v2
Session Status online
Account ngrok-test@example.com (Plan: Free)
Update update available (version 3.23.2, Ctrl-U to update)
Version 3.22.1
Region Japan (jp)
Latency 24ms
Web Interface http://0.0.0.0:4040
Forwarding https://hoge-123-456-7890-01.ngrok-free.app -> http://host.docker.internal:XXXXX
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
3. 外部公開用URLを生成されたURLを使って、Api.base_path
に指定する
'Api' => [
'base_path' => 'https://hoge-123-456-7890-01.ngrok-free.app/api',
'endpoints' => [
'login' => '/users/login',
],
],
この設定にした状態で、ログイン画面から操作を実行すると、、、
接続(ログイン)成功🙌
APIからも成功ステータスが返されてました。
所感
当初はローカル環境同士での接続を試みて失敗していましたが、
ngrokを使うことで 「外部から参照されるAPIとしての形」 に変えることができて問題を解消できました。
ほか参考にした記事