Laravel8 ホスト名をapp.urlに強制する

記事について

dockerのAサービスとBサービス間でAPIのテストを行っていて、さらにBサービスからメールを送信をするような場合、routeメソッドを使ってURLを記載するとドメイン名がコンテナ名になって困ったことがあるので、ドメイン名をconfig/app.phpに書かれているURLに強制する方法。

要するにサービス間通信でドメイン名をコンテナ名にしないでURLにする方法。

結論 AppServiceProviderを修正する

AppServiceProviderを修正する。

...
use Illuminate\Support\Facades\URL;

class AppServiceProvider extends ServiceProvider
{
...
    public function boot()
    {
        /*
         * ROOTURLをアプリケーションのURLに強制する
         */
        URL::forceRootUrl(config("app.url"));
    }
}

どんなとき起こるのか

以下、事象の説明しか書いていないので、飛ばしてもOK。

以下のようなサービスが2つ定義してあり、myappがWebサービス、myapiがapi専用のサービスとする。

version: '3'

volumes:
  myapp-php-fpm-socket:
services:
  nginx:
    container_name: myapp-nginx
    build:
      context: ./nginx
    volumes:
      - myapp-php-fpm-socket:/var/run/php-fpm
      - ../../myapp:/var/www
    depends_on:
      - app
    networks:
      - myapp-network
      - local-network
    environment:
      VIRTUAL_HOST: "myapp.localhost"

  app:
    container_name: myapp-app
    build:
      context: ./app
    volumes:
      - myapp-php-fpm-socket:/var/run/php-fpm
      - ../../myapp:/var/www
    networks:
      - myapp-network
      - local-network
version: '3'

volumes:
  myapi-php-fpm-socket:
services:
  nginx:
    container_name: myapi-nginx
    build:
      context: ./nginx
    volumes:
      - myapi-php-fpm-socket:/var/run/php-fpm
      - ../../myapi:/var/www
    depends_on:
      - app
    networks:
      - myapi-network
      - local-network
    environment:
      VIRTUAL_HOST: "myapi.localhost"

  app:
    container_name: myapi-app
    build:
      context: ./app
    volumes:
      - myapi-php-fpm-socket:/var/run/php-fpm
      - ../../myapi:/var/www
    networks:
      - myapi-network
      - local-network

この構成の状態で、myapp → myapi へAPI呼び出しを行い、myapiからメールを送るとする。

例えば、myappからmyapiの会員登録APIを呼び出す例。以下はmyapp側(呼び出し側)のサンプル。

    // ローカルdocker環境から呼ぶ場合のURL ドメイン名はアクセス先のコンテナ名
    $url = 'http://myapp-nginx/api/v1/user/register';
    $client = new \GuzzleHttp\Client();
    return $client->request('POST', $url, [
        'headers' => [
            'api-token' => 'tokentoken',
        ],
        'form_params' => [
            "email"      => $request->email,
            "name"      => $request->name,
        ],
    ]);

myapiでいろいろごにょごにょして、結果メールを送るときのテンプレートの内容。

...
▼ログインはこちら
{{ route('user.login') }}

で、この状態で送られてくるメールのURLが、「https://myapi.localhost/user/login」となってほしいのだが、コンテナ名でAPI通信をしているからかドメイン名にコンテナ名が入ってしまい、「https://myapi-nginx/user/login」となる。それを解消する方法。

余談

Webサーバ(nginx等)とアプリケーションサーバを分離しているような構成の場合(上の例のような場合)、APIの呼び出しはAサービスのアプリケーションサーバ→BサービスのWebサーバという通信経路になるので、dockerの設定でアプリケーションサーバ側にも共通ネットワークに接続できるようにしておかないと延々とタイムアウトするので注意。

特に問題なければ全部のコンテナに共通ネットワークを定義しておくのが楽。

コメント

タイトルとURLをコピーしました