LoginSignup
19
25

More than 3 years have passed since last update.

【docker】好きなドメイン名(別名)でコンテナ間通信したい【compose】

Posted at

Laravelの開発環境をdockerで作っているのですが、先日とある要件のため、自由なドメイン名でコンテナ間通信をしなければならなくなりました。
dockerへの理解がまだまだ足りないがために、ちょっとハマってしまったので備忘録として残したいと思います。

構成

DB等省略している部分もありますが、docker-composeの構成はこんな感じです。

docker-compose.yml
version: '3'

services:
  nginx:
    build: ./nginx
    container_name: "laravel-nginx"
    environment:
      TZ: "Asia/Tokyo"
    ports:
      - "8080:80"
      - "443:443"
    volumes:
      - ./project:/var/www/html
  php:
    build: ./php
    container_name: "laravel-php"
    environment:
      TZ: "Asia/Tokyo"
    volumes:
      - ./project:/var/www/html

laravel-phpコンテナにLaravelプロジェクトを配置し、laravel-nginxコンテナで配信する、というような構成です。

コンテナ間で自由なドメイン名でcurlとかしたい!

laravel-phpにログインしてlaravel-nginxcurlするには、通常以下のような感じでOKです。

$ docker-compose exec php /bin/bash
$ curl -k https://laravel-ngix/api/foo/bar

もちろんlaravel-nginxの部分はコンテナのipアドレスでもOKです。

では、何らかの理由で自由なドメイン名をつけてコンテナ間通信を行いたい場合はどうすれば良いのでしょう。
単純にコンテナ名を変えれば良いのでしょうか
でもどこかに影響が出てしまったら嫌ですよね。
そこでこんな感じにしてみます。

コンテナにドメイン名(別名)をつけてcurlとかする

答えはいつも公式ドキュメントにあります。

docker-compose.yml
version: '3'

services:
  nginx:
    build: ./nginx
    container_name: "laravel-nginx"
    environment:
      TZ: "Asia/Tokyo"
    ports:
      - "8080:80"
      - "443:443"
    volumes:
      - ./project:/var/www/html
    #ここを追加
    networks:
      default:
        aliases:
          - yoursukinanamae.local
  php:
    build: ./php
    container_name: "laravel-php"
    environment:
      TZ: "Asia/Tokyo"
    volumes:
      - ./project:/var/www/html

これでデフォルトネットワークでyoursukinanamae.localが名前解決できるようになりました。
docker-composeを再起動して以下を実行してみてください。

$ docker-compose exec php /bin/bash
$ curl -k https://yoursukinanamae.local/api/foo/bar

curlくんが元気に応答してくれるようになりました。

networksキーは、別のネットワーク上のコンテナと通信するために使う機能という認識でしたが、場合によっては同一ネットワークに属するコンテナ間でも使いどころがあるんですね。
いろいろと勉強になりました。

以下読み飛ばしてもいいところ

何故上記のようなことを設定したかった、という話なので、興味がない方は読み飛ばしてください。

私の環境で問題になったのは、ホストOSでhttps://localhost/api/*をPHPのソース上で実行した場合です。
※本記事のdocker-compose.ymlで環境構築し、Laravelをインストールして作っています。

このようなAPIがあったとします。

routes/api.php
Route::get('/test', 'TestApiController@testApi')->name('test-api');
TestApiController.php
public function testApi()
{
    // 何らかの処理
    return $json;
}

これを以下のように呼び出します。

TestWebController.php
public function testWeb()
{
    // https://localhost/api/test
    $url = route('test-api');
    $client = new \GuzzileHttp\Client();
    $response = $client->get($url);
    $content = $response->getBody()->getContents();
    $json = json_encode($content);

    return view('view');
}

上記はエラーになります。
$urlに格納されている値がアクセス可能なURLではないからです。
https://localhost/api/testにアクセスできないというのはどういうことなのでしょうか
これはWebサーバーとAPサーバーが別々のコンテナであることが原因です。

リクエストを投げるべきIPアドレスが違う

PHPを実行しているコンテナ → laravel-phpコンテナ(IP Address: 192.168.0.1)
Webサーバー → laravel-nginxコンテナ(IP Address: 192.168.0.2)

上記で実行したlocalhostのipアドレスは192.168.01(laravel-php)です。
つまり、以下を実行したことと同意です。

laravel-php
$ docker-compose exec php /bin/bash
$ curl -k https://localhost/api/test
// もしくは curl -k https://192.168.01/api/test

laravel-phpは、PHPを実行しているだけで、Webサーバーは立っていません。
そこにGETリクエストを投げたところで、応答があるわけがないのです。
本当は192.168.0.2(laravel-nginx)に投げて欲しいのに......

解決するには

まず、コンテナのipアドレスを指定することを考えました。
ですが考えてすぐ却下
立ち上げ直したらipアドレスは変わってしまいますしね。

次に、コンテナ名を指定してみることを考えました。
開発環境ですし、正直これでよかったのですが、せっかくならドメイン名っぽいの付けたいよねとなり、今回紹介した方法に落ち着きました。

WebサーバーコンテナにGETリクエストするように変更する

本記事で紹介したdocker-comose.ymlの設定が終わったら、Laravelの.envを以下のように変更します。

.env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
- APP_URL=https://localhost
+ APP_URL=https://yoursukinanamae.local

ここを変えないとPHPUnit実行時に、route('name')のドメインが変わってくれません。

次に、ホストOSの127.0.0.1(localhost)をWebサーバーコンテナと同じドメイン名でアクセスできるようにします。
そうすることで、ブラウザから実行した際に、route('name')で取得できるドメインがhttps://yoursukinanamae.localになります。

hostsファイルに記述します。

私の環境はWindows 10なので、hostsファイルは
C:\Windows\System32\drivers\etc\host
にあります。
ちなみにMacやLinuxの場所は
/etc/hosts

hostsファイルを管理者権限なりsudoなりで開き、以下を追加します。

127.0.0.1 yoursukinanamae.local

念の為、キャッシュをクリア

C:\>ipconfig /flushdns
mac
// macはバージョンによってコマンド違うことがあるので注意
$ sudo killall -HUP nDNSResponder
linux
$ /etc/rc.d/init.d/network resatart
or
$ /etc/rc.d/init.d/network reload

上記で反映されないのならマシン再起動してください。
これで設定は完了です。

以上です。

参考

docker docs
どうしても hosts の設定が反映されない場合の12通りの確認事項
Qiita: Macでhostsファイルを変更・反映
調べ物メモは今日も山積み

19
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
25