🐳

[Laravel Sail v11.x, Docker] DBエラーにぶち当たったときに試すこと9選

2024/06/19に公開

はじめに

この記事はLaravel SailやDockerなどのプロジェクトで、DB周りの問題にぶち当たって受け出せない人のための記事です。
今回言語はPHP、フレームワークはLaravel、RDBSはMySQLを使ってますが、他の構成(Ruby on Rails, Django, PostgreSQLなど)でも役に立つ内容になるかと思います。

概要

ローカルホストにアクセスして、こんな感じのメッセージが出てきてませんか?

SQLSTATE[HY0001 |2002] Connection refused (Connection: ...以下略

あるいはDocker Desktopのコンテナをみると、MySQLのcontainerだけExcitedになってませんか?

この手の問題に出くわしたら対処すべき2 Stepがあります。

  1. DBの情報を正しく設定する
  2. 正しく設定したDB情報を反映する
    原因は大体DB情報が間違っている、あるいは正しいけど情報が反映されていない、のどちらかかと思われます。
    具体的にどうやって解決するかをまとめていきたいと思います。

チェックすべきファイル

  • ./.env ... 環境変数をまとめるファイル
  • ./docker-compose.yml ... Docker Composeを実行するためのファイル
  • ./config/database.php ... データベースの設定を管理するための設定ファイル
  • ./config/queue.php ... キューシステムの設定を管理するための設定ファイル

アプリケーションとDBと接続するには MYSQL_DATABASE とか DB_USERNAME といったような環境変数を正しく設定する必要があります。
この環境変数が書かれているのが主に上の4つファイルのいずれか、またはすべてです。

でもって、Laravel 11でLaravel sail公式のチュートリアルのままやってエラーになるので修正が必要だったりします。そのまま動いたらいいのに...
https://laravel.com/docs/11.x/sail

DBの情報を正しく設定する方法5選

ということで、ここからは動かない原因とその対処法をざっと紹介していきます。
まずはDBの設定周りから。

1.使用するRDBSを変更する

Laravel Sail v11.xではデフォルトだとSQLiteが設定されているので、MySQLなど使いたい場合はこれを変更する必要があります。
具体的にはDB_CONNECTIONでファイル内検索をかけ、その値を任意のRDBS名に変えます。例えばMySQLの場合は下記のようにします。

# NG
DB_CONNECTION=sqlite

# OK
DB_CONNECTION=mysql
# NG
  'default' => env('DB_CONNECTION', 'sqlite'),

# OK
  'default' => env('DB_CONNECTION', 'mysql'),

*queue.phpには変更箇所が2箇所あります。

# NG
  'default' => env('DB_CONNECTION', 'mysql'),

# OK
  'default' => env('DB_CONNECTION', 'sqlite'),

*database.phpには変更箇所が default, database, prefix の3箇所あります。

2.DB_HOSTを変更する

DB_HOSTという接続先ホストアドレスを指定する環境変数がありますが、これを変更します。
公式サイトがMySQLならmysqlにしてね、と言ってます。
https://laravel.com/docs/11.x/sail#mysql

# NG
DB_HOST=127.0.0.1

# OK
DB_HOST=mysql
# NG
  mysql:
    environment:
       MYSQL_ROOT_HOST: '%'

# OK
  mysql:
    environment:
       MYSQL_ROOT_HOST: '${DB_HOST}'

${DB_HOST} とすることで .env に設定した DB_HOST を読み取ります。

# NG
        'mysql' => [
            'host' => env('DB_HOST', '127.0.0.1'),
        ]
# OK
        'mysql' => [
            'host' => env('DB_HOST', 'mysql'),
        ]

env('DB_HOST', 'mysql') とすることで、第1引数で .env に設定した DB_HOST を読み取り、失敗したら第2引数の値を設定します。
ところで database.php は 'connections' => [ ... ] 内に他にもsqliteやmariadbなどの記述がありますが、使わないRDBSは削除してOKです。

3.DB_PASSWORD を設定する

デフォルトではDB_PASSWORDは未設定ですが、ここに任意の値を入れます。

# NG
DB_PASSWORD=

#OK
DB_PASSWORD=test1234
# NG
        'mysql' => [
            'password' => env('DB_PASSWORD', ''),
        ]

# OK
        'mysql' => [
            'password' => env('DB_PASSWORD', 'test1234'),
        ]

4.DB_URLを削除する

./config/database.php には環境変数 DB_URL を読み取る記述がありますが、.env にはデフォルトでこのような値は設定されていません。
ない変数を読み取ろうとしたらエラーの原因になりそうですし、使わない変数をおいておくのも運用上よろしくないのでこれは削除します。
なくても動くし、正直なんのために使われる変数なのかいまいちわかりません。
ググってもほとんどヒットしないし、公式にも若干情報あるけれどいまいち用途はわかりませんでした。
https://laravel.com/docs/11.x/database#configuration-using-urls

        'mysql' => [
            'url' => env('DB_URL'), # 削除する
        ]

5.最新のDocker imageを設定する

正直これがエラーの解決につながったか不明ですが、やってみる価値はあるでしょう。
Laravel Sailにデフォルトで設定されているRDBSのDockerイメージはバージョンが古かったりします。それを上げることで解決できるかもしれません。(または下げる)

# NG
    mysql:
      image: 'mysql/mysql-server:8.0'

# OK
    mysql:
      image: 'mysql/mysql-server:latest'

正しく設定したDB情報を反映する方法5選

DBの設定を正しく行えても、反映されてなければ意味がありません。
Laravel SailやDockerを使っている場合、ファイルの一部をただ変えても反映されないことがあります。
そこでここからはファイルを変更したあとに実行すべきコマンドや処理を紹介します。

6.キャッシュをクリアする

下記はLaravelの各ファイルを変更した際にキャッシュをクリアするコマンドです。
今回のケースで使うのはconfigのキャッシュ操作だと思いますが、ほかのも一応紹介します。
サクッと実行できるのでこれで解決するなら一番早い。

# 設定ファイル(config/)のキャッシュをクリア
./vendor/bin/sail php artisan config:cache

# アプリケーションレベルのキャッシュをクリア
./vendor/bin/sail php artisan cache:clear

# アプリケーションのルートキャッシュをクリア
./vendor/bin/sail php artisan route:clear

# ビューのキャッシュをクリア
./vendor/bin/sail php artisan view:clear

ちなみに ./vendor/bin/sail php artisan optimize:clear を入力するとこれら4つを一気に実行してくれます。

7.マイグレーション

DBを変更したらマイグレーションが必要です。今回みたいなDB関連のエラーならどこかのタイミングで1度はお世話になる可能性大。

./vendor/bin/sail php artisan migrate

データベースをクリーンな状態にリセットしてマイグレーションするならオプションで fresh をつける。

./vendor/bin/sail php artisan migrate:fresh

ただし、freshをつけての実行はデータベース内の全てのデータを失うため、すでにDBに重要なデータが入ってるなどの状況では推奨されません。とくに本番やステージングでは使わないようにしましょう。

8.Dockerをキャッシュクリアして再ビルド

docker-compose.yml を変更したら実行したほうがいいコマンド。
オプションに --no-cache を含めることでキャッシュを使わずまっさらな状態でビルドする。

./vendor/bin/sail build --no-cache

9.Docker関連の不要なデータを削除

Dockerの不要なリソースを削除します。これには、未使用のDockerイメージ、コンテナ、ボリューム、ネットワークなどが含まれます。
いろいろ試行錯誤しすぎて無駄なDocker関連のデータが蓄積していたら実行しましょう。

# 使用していないコンテナ、ネットワーク、イメージ(関連付けられていない匿名イメージを含む)を全て削除
docker system prune -a

# 使用していない Docker ボリュームを削除
docker volume prune -a

必要なDockerコンテナがあるならそれを避けつつ、ピンポイントでコンテナIDを指定して削除するなどしないといけないので注意。

さいごに

これらのいずれか、または一通りを実施したら大抵のエラーは解決するのではと思います。
(最後に ./vendor/bin/sail up してlocalhostにアクセスするのを忘れずに)

ちなみにプログラミングスクールとかエンジニアさん向け転職支援とかやってるので、よかったチェックしてください◎
https://bug-fix.org
https://bug-fix.org/siid

Discussion