Laravel

Laravel でSession cookie が設定できない – .env のSESSION_DOMAIN設定を修正

皆さまこんにちは、ウチイダです。

先日、新規開発でLaravelの初期セットアップをしていた時につまづいた内容をメモします。

今回の開発は、LaravelをバックエンドのAPI サーバーとして、React で作られたSPAをフロントエンドに配置する構成でした。

Vite で起動したローカルのReactアプリケーション(localhost:5173) から、Laravelが動いているDockerコンテナ(localhost:80)に向けてリクエストをしたところ、警告が発生しました。

ResponseのSet-Cookie で警告が表示

レスポンス自体はちゃんと受け取れているようですが、Set-Cookieのところに警告アイコンが表示されています。

⚠️のアイコンにマウスオンしてみると、以下のようなメッセージが。

This attempt to Set-Cookie header was blocked because its domain attribute was invalid with regards to the current host url

現在のURLに対して、Set-Cookie のドメイン指定が不正なので、Cookieが保存できない、といった警告です。

レスポンスの内容をよく見ると、Set-Cookieのドメインプロパティが確かにおかしいです。

domain=.localhost

localhostの先頭に、. がついています。.env ファイルでSESSION_DOMAIN=.localhost と設定していることが原因でした。

以下のように修正したところ、解消しました。

# SESSION_DOMAIN=.localhost . がついているとNG
SESSION_DOMAIN=localhost

本番環境では、ReactとLaravelをサブドメインに分けて配置して運用する想定だったので、CORS対策としてドメインの先頭に.をつけていました。

Set-Cookie ヘッダーのdomain プロパティで、先頭に . をつけてドメイン指定すると、サブドメイン間でCookieを共有できるようになります。

この先頭の . を、ローカル用の .env からとり忘れていたのが原因でした。

localhost の指定では、.がついているとドメインを正しく認識できず、動かなくなってしまうのです。

ローカル用とサーバーにデプロイして使う.env の内容を分けて管理しておく必要がありますね。

以上です。あなたのお役に立てればうれしいです。

seeders のサブディレクトリ内に配置したSeeder クラスを、artisan CLI から実行したい:–class にname space を指定する

皆さまこんにちは、ウチイダです。

LaravelのSeederが便利でよく使っています。

テスト用のレコードを生成する処理をまとめておくと、いろいろ使いまわしがしやすいです。

でも、困るのがファイル数が増えてきたときの取り扱いです。database/seeders ディレクトリに全部入れてしまうと、ファイルを探しづらくなってしまいます。

というわけで、Seederクラスをサブディレクトリに分けることにしました。

検証環境

  • Laravel v9.43.0
  • PHP v8.1.13
  • Windows11 21H2

サブディレクトリにSeeder クラスファイルを作る

artisan で生成するときに、サブディレクトリを含めて指定するだけでOKです。

$ sail artisan make:seed Subfolder/SampleSeeder

   INFO  Seeder [database/seeders/Subfolder/SampleSeeder.php] created successfully.  

database/seeders/Subfolder 配下に、Seeder クラスを作ってくれました。

artisan コマンドから、サブディレクトリのSeeder を直接呼び出す

ここからが本題です。artisan db:seed は、–class に実行するSeeder クラス名を指定することができます。

これを使って、サブディレクトリにあるSeeder を呼び出します。

ちょっとだけ修正して、テキストだけ表示するように変更します。

<?php

namespace Database\Seeders\Subfolder;

use Illuminate\Database\Seeder;

class SampleSeeder extends Seeder
{
    public function run()
    {
        echo "サブフォルダのSeeder だよ~\n";
    }
}

それでは、いざ実行!

# name space を記述しないとエラー
$ sail artisan db:seed --class='SampleSeeder'

   INFO  Seeding database.  


   Illuminate\Contracts\Container\BindingResolutionException 

  Target class [Database\Seeders\SampleSeeder] does not exist.

クラスの名前解決ができません。クラス名だけ書くと、Database/Seeders 内を探すようになっているようです。

では追加の名前空間を指定すると…?

# Seeders 以降のname space を記述してもエラー
$ sail artisan db:seed --class='Subfolder\SampleSeeder'

   INFO  Seeding database.  


   Illuminate\Contracts\Container\BindingResolutionException 

  Target class [Subfolder\SampleSeeder] does not exist.

これでもエラーです。

名前空間を指定する(–class に \ を含む文字列を渡す)と、Database/Seeders は使わなくなってしまいました。

仕方ないので、全部指定します。

# name space を全部書くと名前解決できる
$ sail artisan db:seed --class='Database\Seeders\Subfolder\SampleSeeder'

   INFO  Seeding database.  

サブフォルダのSeeder だよ~

今度は実行できています。これは面倒…!

少し調べてみたところ、composer.json のautoload の設定を変えることで対応するやり方がいくつか見つかりました。

しかし、更新日付が古く、おそらくLaravel5 か 6 のころの話だと思われます。

また、クラス名の解決の仕方はdb:seed の挙動なので、autoload の設定でどうにかなるものではないような気がしています。

とりあえずname space を全部書くか、artisan CLI からの直接実行はあきらめるか、のどちらかになりそうです。

以上です。あなたのお役に立てればうれしいです。

Laravelのqueue をcron で動かすときの設定 — レンタルサーバ会社さんにお叱りを受けたので修正した

こんばんは、ウチイダです。

結構前なのですが、しょうもないヤラカシをしたので、自戒を込めて記事にしておきます。

冒頭、まずはお詫びを。エックスサーバーさん、その節は大変失礼いたしました🙇

何があったのか

それは、エックスサーバー上でLaravelのアプリケーションを運用するお仕事でした。

そこそこ本格的なアプリケーションで、外部サービスのAPIへのリクエストなどの重い処理が走るので、ジョブ・キューを使うことにしました。

本来ならドキュメントにもある通り、supervisor などを使ってワーカープロセスをデーモン化したいところです。

しかし、さしものエックスサーバといえども、supervisor は利用できないようでした。

そこで、cron を使ってワーカープロセスを定期的に起動するようにしました。

実際に記述していたcron エントリは以下のような感じです。ディレクトリのパスだけ、ダミーのものに変えています。

* * * * * cd path/to/laravel_project && /opt/php-8.1/bin/php artisan queue:work --max-time=36000 --timeout=36000 --env=production >> /dev/null 2>&1

設定後しばらくしたら、エックスサーバーのサポートからメールで連絡がありました。

要旨としては、契約しているサーバーが高負荷になっており、cron で実行されてるプロセスが原因なので早急に対策せよというものでした。

慌ててエラーログを確認したところ、DBとのコネクションリソースも使い果たしていました…

[2022-07-31 12:40:51] production.ERROR: SQLSTATE[HY000] [1226] User 'my_user' has exceeded the 'max_user_connections' resource (current value: 100) // ...以下略

サポートから指摘があった通り、CPU負荷も高くなっていただろうと思います。

何がいけなかったのか

冷静にcron設定を見直してみたところ、いくつか問題点に気づきました。

  • 重い処理が渡されたときのために –max-time と –timeout を 36000秒(10時間!)というめちゃ大きな値にしている
  • –stop-when-empty オプションをつけていないので、–max-time オプションで指定している秒数、ワーカープロセスが残り続ける
  • cron の起動は最短間隔(1分ごと)にしてあるため、新しいワーカープロセスが頻繁に生成される

つまり、古いプロセスが消えることなく、新しいプロセスを次々に作ってしまう設定だったということです。

ちょっと落ち着いて考えればわかりますね…あほすぎる…

cron エントリの修正

今回の原因は、古いワーカープロセスが終了せず、時間の経過とともに増え続けてしまうことでした。

というわけで、以下のようにcronエントリを修正しました。

*/5 * * * * cd path/to/laravel_project && /opt/php-8.1/bin/php artisan queue:work --max-time=300 --timeout=36000 --env=production >> /dev/null 2>&1

修正したのは以下の点です。

  • cron の実行周期を、1分から5分に変更
  • –max-time=300 に指定して、ワーカープロセスの生存時間を5分に設定
  • –timeout は、日に1回のバッチ処理が数時間かかるものがあるので、36000のままにしておく

5分毎にワーカープロセスがcronによって生成され、次の生成までワーカープロセスが少なくとも1つ存在するようにしました。

処理に5分以上かかるジョブが送られると、一時的に2つ以上のワーカープロセスが存在することになります。

そんなに重い処理が頻繁に発生するアプリケーションではなかったので、問題にはならないはずです。

これでも負荷が上がってしまうようなら、VPSとかクラウド環境に移行することをクライアントに提案するつもりです。

ちなみに、Laravel の日本語ドキュメントにも、queue コマンドの使い方は詳しく書いてあります。RTFM!!

https://readouble.com/laravel/9.x/ja/queues.html#running-the-queue-worker

まとめ

あらためまして、エックスサーバーさん、および同一サーバーを利用していた方、ご迷惑おかけしました。

ドキュメントをちゃんと読むことと、ローカルでの動作テストをきちんと行うことを改めて心に刻みました。

この記事を見ているみなさんはこんなアホなミスはしないと思いますが、ヤラカシ事例としてお知りおきください。

以上、あなたのお役に立てれば幸いです。

Laravel artisan でClassloader のエラーが発生 – composer dumpautoload でオートロード設定を更新

こんばんは、ウチイダです。

Laravel にいろいろなパッケージを追加していたところ、あるタイミングからartisan コマンドの実行で以下のようなエラーが発生するようになりました。

例ではEvent クラスの生成コマンドを試していますが、ほかのコマンドでも同様です。

$ php artisan event:generate

   ErrorException

  include(/var/www/html/vendor/composer/../../app/Events/Something.php): Failed to open stream: No such file or directory

  at vendor/composer/ClassLoader.php:571
    567▕  * @private
    568▕  */
    569▕ function includeFile($file)
    570▕ {
  ➜ 571▕     include $file;
    572▕ }
    573▕

      +2 vendor frames
  3   [internal]:0
      Composer\Autoload\ClassLoader::loadClass()

      +27 vendor frames
  31  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

どうやら、Composerのオートロードがうまく動作していないようです。

Composerでのパッケージ追加中に、何かの操作をミスったか、composer.jsonの設定を間違えたようです。

以下のコマンドで修正をかけます。

$ composer dumpautoload
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: barryvdh/laravel-debugbar
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Discovered Package: spatie/laravel-ignition

# ... 他にもいろいろ表示されました ...

Package manifest generated successfully.
Generated optimized autoload files containing 5207 classes

再度、Event クラスの生成を試したところ、うまくいきました。

$ artisan event:generate
Events and listeners generated successfully.

以上です。あなたのお役に立てれば幸いです。

Laravel Http クライアントで、Gzipのデータを取得したい

こんばんは、ウチイダです。

Amazon Ads API を利用して、広告費用を最適化するアプリケーションの開発をご依頼いただきました。

ドキュメントが今のところ英語しかないので、頑張って読み解きつつ進めています。

https://advertising.amazon.com/API/docs

LaravelでAmazon Ads APIとの通信部分を実装しているなかで、広告パフォーマンスのレポートデータをダウンロードする部分で少し苦労したのでメモしておきます。

Amazon Ads API では、クリック数や広告経由の売り上げなどの情報を取得するために、以下の手順を踏む必要があります。

  1. レポートデータの生成をリクエスト
  2. 最大15分ほど、レポートデータが生成されるのを待つ
  3. レポートデータが生成されたら、Amazon S3からダウンロードする

3でダウンロードされるデータがgzipで圧縮されていたので、うまくレスポンスを受け取るのに少し工夫が必要でした。

ちなみに、手順1, 2はLaravel Httpのドキュメントを見ながら結構簡単に実装できました。

https://readouble.com/laravel/9.x/ja/http-client.html

実際にうまく動作したコードは、以下のような感じです。

// 冒頭で、Http ファサードを読み込んでおく
use Illuminate\Support\Facades\Http;

$response = Http::
    withHeaders([
    'Content-Type' => 'application/json',
    'Amazon-Advertising-API-ClientId' => 'CLIENT_ID', // あらかじめ取得したClient IDを設定
    'Amazon-Advertising-API-Scope' => 'PLOFILE_ID', // あらかじめ取得したProfile IDを設定
])
    ->withOptions(['decode_content' => 'gzip']) // ★gzip形式での受け取りする
    ->withToken('ACCESS_TOKEN') // あらかじめ取得したアクセストークンを設定 WithToken() がBearer の記述など行ってくれる
    ->get("https://advertising-api-fe.amazon.com/v2/reports/{$reportId}/download"); // あらかじめ発行リクエストしたレポートのIDを設定

dump($response->body()); // gzip のバイトデータそのまま表示してみる
dump(gzdecode($response->body())); でコードしてもともとのデータを表示する

downloadのエンドポイントは、存在するレポートデータのIDに対してリクエストされたら、リダイレクトしてAmazonS3 バケットに配置されたデータを返してくれます。

Content-typeはapplication/jsonにしつつ、gzipのデータを取得するように設定する必要があります。

ポイントはwithOptions()でgzipのデータを受け取ることを記述している点です。

‘decode_content’ で指定できるのですね。

この設定値はLaravelのドキュメントには記載されていなくて、Guzzle のドキュメントを見る必要がありました。

https://docs.guzzlephp.org/en/stable/request-options.html#decode-content

ちなみに、ヘッダー内に書く場合は以下のようになります。

// 冒頭で、Http ファサードを読み込んでおく
use Illuminate\Support\Facades\Http;

$response = Http::
    withHeaders([
    'Content-Type' => 'application/json',
    'Amazon-Advertising-API-ClientId' => 'CLIENT_ID', // あらかじめ取得したClient IDを設定
    'Amazon-Advertising-API-Scope' => 'PLOFILE_ID', // あらかじめ取得したProfile IDを設定
    'Accept-Encoding' => 'gzip' // ★ここにgzipを指定
])
    ->withToken('ACCESS_TOKEN') // あらかじめ取得したアクセストークンを設定 WithToken() がBearer の記述など行ってくれる
    ->get("https://advertising-api-fe.amazon.com/v2/reports/{$reportId}/download"); // あらかじめ発行リクエストしたレポートのIDを設定

withOptions() がなくなってチェインするメソッドが減ったので、今回の場合であればこっちの方がすっきりします。

withToken()も、Bearer の記述をコード内に書けばwithHeaders() に含めることができるので、もっとまとめてしまうこともできます。

ウチイダ的にはwithToken() を使う方が楽なので、このままにしています。

以上です。あなたのお役に立てれば幸いです。

Laravelで複数のDBへ接続する

こんばんは、ウチイダです。

この前お引き受けしたお仕事で、複数のDBサーバを利用する案件がありました。

  • 全データを集積しているDB(マスタDB)から必要な内容を取得し、自前のDB(アプリDB)に保存
  • アプリDBには、独自に算出して業務に用いるカラムがある

という感じに開発するもので、モデル自体を別のものとして扱う方がよさそうでした。

というわけで、モデルごとに、別のDBのテーブルと連携させるための設定を調べました。

それをメモしておきます。

ちなみに、利用したLaravelのバージョンは9です。

今後の新規プロジェクトで利用できると思います。

1. .envに接続情報を分けて記載する

.envに、二つのDBの接続情報を記載します。以下のような感じです。

※もちろん、値はすべて仮のものです。

# 自前のDB(アプリDB)接続設定
APP_DB_CONNECTION=app
APP_DB_HOST=app.example.com
APP_DB_PORT=3306
APP_DB_DATABASE=app
APP_DB_USERNAME=app_user
APP_DB_PASSWORD=password

# データを集積しているDB(マスタDB)の接続設定
MASTER_DB_CONNECTION=master
MASTER_DB_HOST=master.example.com
MASTER_DB_PORT=3306
MASTER_DATABASE=master
MASTER_DB_USERNAME=master_user
MASTER_DB_PASSWORD=password

2. LaravelのDB接続設定で、envに記載した内容を反映

config/database.php で、データベースの接続設定がまとめられています。

.envで指定した内容がLaravel内で利用できるように設定していきます。

設定項目が多いように見えますが、デフォルトで「mysql」 という名前の接続情報があるので、それをベースに一部を書き換えるだけなので、それほど難しくはありません。

    /* 18行目あたり */
    /* デフォルトの接続情報はappにする */
    'default' => env('APP_DB_CONNECTION', 'app'),

    /* connections の中で、.envに指定した内容を記入する */
    'connections' = [
        /* アプリDB用の接続設定 */
        'app' => [
            'driver' => 'mysql',
            'url' => env('APP_DB_URL'),
            'host' => env('APP_DB_HOST', '127.0.0.1'),
            'port' => env('APP_DB_PORT', '3306'),
            'database' => env('APP_DATABASE', ''),
            'username' => env('APP_DB_USERNAME', ''),
            'password' => env('APP_DB_PASSWORD', ''),
            'unix_socket' => env('APP_DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

        /* マスタDB用の接続設定 */
        'app' => [
            'driver' => 'mysql',
            'url' => env('MASTER_DB_URL'),
            'host' => env('MASTER_DB_HOST', '127.0.0.1'),
            'port' => env('MASTER_DB_PORT', '3306'),
            'database' => env('MASTER_DATABASE', ''),
            'username' => env('MASTER_DB_USERNAME', ''),
            'password' => env('MASTER_DB_PASSWORD', ''),
            'unix_socket' => env('MASTER_DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],
    ],

3. モデルファイルで、接続先のDBを指定する

次に、モデルファイルに$connection を追加し、利用する接続先の名称を指定します。

以下は、アプリDBのsamples テーブルを利用するモデルの例です。

<?php

namespace App\Models\App;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Sample extends Model
{
    use HasFactory;

    /* アプリDBへ接続する */
    protected $connection = 'app';
}

4. モデルを使ってみる

これで準備は整いました。ためしに、コントローラから呼び出してみます。

<?php

namespace App\Http\Controllers;

use App\Models\App\Sample;

class ConnectionTestController extends Controller
{

    public function test()
    {
        /* samples テーブルから1件データを取り出してみる */
        dd(Sample::first());
    }
}

ルーティング設定してブラウザからアクセスし、データが表示されたら成功です。

同じ要領で、マスタDB用のモデルも作成できます。

cinfig/connection.php に接続情報をまとめていることが理解できていれば、記述するコードの内容は想定してたより難しくありません。

フレームワークごとに設定の仕方はいろいろなので、このあたりは実際に案件を通じて経験したり、じっくりドキュメントなどを読んで理解を深めていくことが不可欠ですね。

おまけ:DB ファサードで接続先を指定する

上記の設定をした前提で、DB ファサードからマスタDBへ接続する場合は以下のようにします。

DB::connection('master')->table('sample')->first();

connection() メソッドを書かなければ、デフォルト設定しているapp が使われます。

以上です。あなたのお役に立てれば幸いです。

Laravel 9 にLaravel Mix でjQuery を追加する

こんばんは、ウチイダです。

Laravelの案件でも、フロントをjQueryにするパターンはちょいちょいありますね。

初期構築の際、いつもインストールに手間取るので、未来の自分のために書いておくことにします。

vueのやり方は検索に出てくるんですけど、jQuery はないのはなぜなのでしょうね…?

1. npm でjQuery をインストール

$ npm install jquery --save-dev 

2. webpack.mix.js を編集

autoload() でjQueryを指定するだけで、public/app.jsにも含まれるし、$で呼び出せるようにもなります。

bootstrap.js などrequire() を書く必要があるのかと思ってしまうのですが、それもいりません。

mix.js("resources/js/app.js", "public/js")
    .sass("resources/scss/custom.scss", "public/css")
    .postCss("resources/css/app.css", "public/css", [
    ])
    /* 以下を追記 */
    .autoload({
        jquery: ["$", "window.jQuery"],
    });
    /* 追記ここまで */

3. npm run でコンパイル

コンパイルします。

$ npm run dev

全く関係ないですが、コンパイルは機械語への変換のことだと理解していたので、JavaScript を「コンパイルする」という言葉遣いはいまだに違和感がぬぐえないんですよね…

4. View で読み込み

Blade テンプレートのヘッダ部分などに、以下を追記します。

<script src="{{ mix('js/app.js') }}"></script>

以上です。

あなたのお役に立てれば幸いです。

Laravel sail で外部APIアクセスエラーする

こんばんは、ウチイダです。

先日お引き受けした案件で、Laravelから外部APIを利用する実装が必要になりました。

いつものように、ローカル環境のSailで動作確認しつつ実装していきます。

しかし、Httpファサードで外部APIにアクセスしようとするとResolving タイムアウトが発生してしまいました。

どうやら、名前解決に失敗しているみたいです。

Dockerネットワーク外のドメインの名前解決をするDNSが設定されていないことが原因だったので、Docker-compose.ymlに、dnsを設定しました。

# For more information: https://laravel.com/docs/sail
version: '3'
services:
    laravel.test:
				# (略)

        # 外部DNSを指定する
        dns: 8.8.8.8

いったんコンテナを再起動してDNSを認識できるようにしてからリトライ。

APIサーバを見つけて、レスポンスを取ることができました。

ちなみに、これに苦労してあれこれコントローラのアクションメソッドに書き散らかしてしまったので、その後サービスクラスに切り出すのにそこそこ苦労しました(現在進行形でしてます)。

思いがけない沼にはまると、設計やクラス分解がおろそかになりがちなので気を付けたいです。

以上です。

あなたのお役に立てれば幸いです。

Laravel Sailに追加したPhpMyAdminからデータベースにつながらない

先日、Laravel Sailについて質問を受けた内容です。

PhpMyAdminを使いたいということで、自身で調べてdocker-composeにサービスの追加をしたけど、動かないということでした。

Sail を起動して、ブラウザでPhpMyAdminにログインしようとすると、エラーになってしまいます。

ログインの時点でエラー

とりあえずMySQLの疎通確認から。

Laravelコンテナからマイグレーションの実行はできているので、MySQLコンテナ自体はちゃんと動いているようです。

$ sail artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (553.47ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (767.61ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (589.25ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (380.02ms)

コンテナ起動時にも、ちゃんとphpmyadminコンテナが起動してます。

$ sail up -d
Creating network "laraveltest_phpmyadmin_sail" with driver "bridge"
Creating laraveltest_phpmyadmin_mailhog_1     ... done
Creating laraveltest_phpmyadmin_redis_1       ... done
Creating laraveltest_phpmyadmin_mysql_1       ... done
Creating laraveltest_phpmyadmin_selenium_1    ... done
Creating laraveltest_phpmyadmin_meilisearch_1 ... done
Creating laraveltest_phpmyadmin_phpmyadmin_1   ... done
Creating laraveltest_phpmyadmin_laravel.test_1 ... done

$ sail ps
                Name                               Command                  State                           Ports
--------------------------------------------------------------------------------------------------------------------------------------
laraveltest_phpmyadmin_laravel.test_1   start-container                  Up             0.0.0.0:80->80/tcp, 8000/tcp
laraveltest_phpmyadmin_mailhog_1        MailHog                          Up             0.0.0.0:1025->1025/tcp, 0.0.0.0:8025->8025/tcp
laraveltest_phpmyadmin_meilisearch_1    tini -- /bin/sh -c ./meili ...   Up (healthy)   0.0.0.0:7700->7700/tcp
laraveltest_phpmyadmin_mysql_1          /entrypoint.sh mysqld            Up (healthy)   0.0.0.0:3306->3306/tcp, 33060/tcp, 33061/tcp
laraveltest_phpmyadmin_phpmyadmin_1     /docker-entrypoint.sh apac ...   Up             0.0.0.0:8080->80/tcp
laraveltest_phpmyadmin_redis_1          docker-entrypoint.sh redis ...   Up (healthy)   0.0.0.0:6379->6379/tcp
laraveltest_phpmyadmin_selenium_1       /opt/bin/entry_point.sh          Up             4444/tcp, 5900/tcp

Laravel本体のコンテナとMySQLのコンテナは疎通してて、PhpMyAdminからだとつながってないような状況なので、コンテナ内でなんか起こってるのかなと目星をつけました。

ご質問者さんに了解を取ったうえで、ボリュームを削除して作り直してみます。

sail down --volumes --remove-orphans
Stopping laraveltest_phpmyadmin_laravel.test_1 ... done
Stopping laraveltest_phpmyadmin_phpmyadmin_1   ... done
Stopping laraveltest_phpmyadmin_meilisearch_1  ... done
Stopping laraveltest_phpmyadmin_selenium_1     ... done
Stopping laraveltest_phpmyadmin_mysql_1        ... done
Stopping laraveltest_phpmyadmin_redis_1        ... done
Stopping laraveltest_phpmyadmin_mailhog_1      ... done
Removing laraveltest_phpmyadmin_laravel.test_1 ... done
Removing laraveltest_phpmyadmin_phpmyadmin_1   ... done
Removing laraveltest_phpmyadmin_meilisearch_1  ... done
Removing laraveltest_phpmyadmin_selenium_1     ... done
Removing laraveltest_phpmyadmin_mysql_1        ... done
Removing laraveltest_phpmyadmin_redis_1        ... done
Removing laraveltest_phpmyadmin_mailhog_1      ... done
Removing network laraveltest_phpmyadmin_sail
Removing volume laraveltest_phpmyadmin_sail-mysql
Removing volume laraveltest_phpmyadmin_sail-redis
Removing volume laraveltest_phpmyadmin_sail-meilisearch

これで直りました。どういう事象でエラーだったのかわからないけど。。。

ボリュームを消しちゃったので、MySQLも空っぽになっています。

このあと、マイグレーション・シーディングをし直してもらいました。

以上です。あなたのお役に立てれば幸いです。

Laravel Sail でコンテナのshellを使う

こんばんは、ウチイダです。

Laravel Sail便利ですよね。docker-compose のラッパーみたいなものなので、学習コストも低くてとても良い感じです。

docker-composeでできることは何でもできるので、困ったらdocker-composeのコマンドを調べるのですが、なかなか覚えられません。

ちょくちょく使うのが、コンテナに入るコマンドです。

# Laravelアプリケーションのコンテナのbashを開く
$ docker-compose exec laravel.test bash

dockerコマンドみたいに、-it とかオプション付けなくてもいいので、まだいいですが、長いですよね。

あるときふとReadoubleを見直してみたら、sail コマンドからコンテナ接続するサブコマンドがちゃんと用意されていました。

# sail コマンドから、Laravel アプリケーソンのコンテナのbashをひらく
$ sail shell

# root ユーザーで接続する場合
$ sail root-shell

# Readoubleにはないけど、以下でもOK
$ sail bash

すごく短くなります。

sailコマンドの中身(vendor/bin/bash)は難しくないshellスクリプトなので、中身を見てみるといろいろ発見があって面白いです。

以上です。あなたのお役に立てれば幸いです。