Laravel環境整えるのに便利なlaradock
私自身はPHPで何かを作ったりすることはほとんどないのだが、質問対応なんかでたまにLaravel関係の質問をされることがある。そんなときいちいちLaravelの環境設定をするのはめんどくさいと思って、Dockerを使って環境構築を自分でやろうとしていた。
だがそんな折に、Laravel環境のセットアップをまとめて行う、Laradockというプロジェクトの存在を知った。設定にえらくハマってしまったのだが、紹介がてら初期設定について解説していきたい。
ちなみに以降はMacを前提とした話なので、Windows環境の人は適宜読み替えて欲しい。また、Dockerの導入については触れていないので、Dockerがインストールされていることも前提となっている。
私はPHPまったくわからないレベルではない。過去にはWordPressのテーマを自作したりしていたこともあるので、ある程度はしっていますレベルだ。PHP特有の罠とか、バージョンによる違いとかそういうことはよく分かっていないが、調べればなんとか解決できる程度の能力は有している。
しかしLaravelに関しての質問になると話は変わって、調べれば分かる程度の質問なら問題ないのだが、実際に環境を用意して実行しなければわからない質問が来ると一気に困る。自分では使いもしないのに、Laravelの環境構築ゼロからやるのかという話で、そこをDockerで省力化しようとしていた。
しかしながら、私はDockerについてもあまり詳しいわけではない。特に自分でゼロから必要な環境を構築しようとすると、どこをどう設定すればよいのかよくわからない。すでに用意されている環境を読み解くのならまだなんとかなるのだが、自分でゼロからやるのは難しいというそんなレベル感だ1。
そんな私にぴったりなLaradockなるプロジェクトを知ることとなった。Laravel実行に必要なもろもろをセットにして、docker-composeを使って操作できる便利なやつである。
便利なやつなのだが、これを使ってLaravelを実行できるようにするまでにものすごくハマってしまった。原因は明白で、自分の頭で考えずにハウツー情報をそのまま使っていろいろ試してしまったせいである。これはハマるときのよくあるパターンなので気をつけよう2。
何が罠かと言うと、この記事を執筆時点(2019年8月31日)において、Laravelが最新のMySQLのデフォルトの認証方式に対応していない問題がある。これに対処するのにドハマリしたという話である。
https://qiita.com/ucan-lab/items/3ae911b7e13287a5b917
そもそもDockerについてもあまり詳しくないので、それが原因でハマってた部分もあるのだけど。順番でいうと、Laradockでうまく環境が構築できないから始まり、できたと思えばLaravelでDBのマイグレーションが動かないでハマったという感じだ。
Laradockがうまく動かない問題は、なぜかmysqlのサービスが起動しないという謎現象でまずハマった。ドキュメントのインストラクションどおりにやってるはずなのだが、mysqlだけ起動して直後に落ちるという謎現象が発生した。
もっともこれに関してはなんかいろいろやってたら直った。なので原因がよくわからない。MySQLに関する設定がおかしいままdocker-compose upしてしまい、変な状態のままMySQLサービスが動いてしまった可能性がある。いつのまにか動くようになったのでいまひとつ原因を把握しきれていないが、そこは本題ではない。
Laradockでは、ベースとなる設定ファイルがenv-exampleというファイルで用意されている。これを.envファイルとしてコピーして使うのがまず最初にやることだ。
この.envファイルには次の点は最低限、確認しておくべきだろう。
- APP_CODE_PATH_HOST
- DATA_PATH_HOST
- MySQLの設定
とりあえず今回ハマった状態から脱出するため、変更・確認した項目はこの3つである。
これはLaravelのプロジェクトのデータを配置する場所を指定するものである。新規のプロジェクトであれば、laradockディレクトリと同一階層に適当なディレクトリを用意して指定すれば良い。
既存プロジェクトにLaradockを適用する場合は、初期状態のままでよい。既存プロジェクトの中にLaradockをクローンしてきて使うようなので。そのあたりは公式インストラクションを参照されたし。
これはMySQLなどのデータを保存する場所である。デフォルトでは~/.laradock/data
ディレクトリに保存される。
注意すべきは、複数のプロジェクトでLaradockを使う場合、このDATA_PATH_HOSTを分けないとデータが混じってしまう点だ。その場合~/.laradock/data/hoge
などプロジェクト名を追加するなどして対応すればよいらしい。そもそもホームディレクトリ以外に置く場所を確保してもいいだろう。
また、中途半端にMySQLの設定を変更してしまい、うまく動かなくなってしまったので最初からやり直したいときがあるだろう。私にはあった。そんなときは、この~/.laradock/data/mysql
を削除する必要がある。その必要性はない可能性もあるが、issueを見ていたらこれを消したらうまく言ったぜ的な話があったので実行している。
これはLaravelがMySQLの最新バージョンの認証方式に対応するまでの時限措置である。
基本的にはやるべきことは先に紹介したQiitaの記事で書かれていることである。
https://qiita.com/ucan-lab/items/3ae911b7e13287a5b917
LaravelがMySQLの最新バージョンからデフォルト利用されるようになった認証方式、caching_sha2_password
に対応していないのがことの本質である。
私は上記Qiitaの記事の対処法1を使って対処した。つまり、Laradockで接続に使うユーザの認証方式をmysql_native_password
に変更したのである。
この際に必要なのがlaradockの.envファイルにあるMySQLの設定である。これは設定の変更が必要なのではなく、何が設定されているか確認しておけという話だ。
MYSQL_VERSION=latest
MYSQL_DATABASE=default
MYSQL_USER=default
MYSQL_PASSWORD=secret
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.d
こんな感じで設定されているはずなので、これを後で使うため確認しておけということである。
docker-compose up -d nginx mysql
で必要なサービスを起動する。Laradockの場合基本的に使うコマンドはだいたいdocker-compose
である3。
今回はdocker-compose
の説明については全て省く4。
各サービスが起動したらdocker-compose exec workspace bash
でメインとなるサービスにログインする。このworkspaceでLaravelのプロジェクト作成などを行う。
ログインしたらLaravelプロジェクトを作成する。LaradockではComposerが使えるように設定されているので、composer create-project laravel/laravel .
でプロジェクトを作成すれば良い。ちなみに実行する場所は/var/www
である。ログインしたらおそらくそこにいるはずであろうから、そのまま実行すれば良い。実行すればよいが、ちゃんとカレントディレクトリがどこかは確認してやるべきである。
コマンドの最後に.
とカレントディレクトリを指定している。これはLaradockの.evnファイルの設定で指定した、APP_CODE_PATH_HOSTの場所にLaravel関連のファイルが作成される。もしうまく動かない場合は、APP_CODE_PATH_HOSTの指定を確認し直してからやり直そう。
Laravelのインストールが終わったらLaravelの.envファイルを修正する。.envファイルは2つ出てくるが、ここではLaravelの.envファイルを修正するのだ。重要なので2回言った。
修正すべきはDB_HOSTの値だ。おそらく127.0.0.1が指定されているので、これをmysqlに変更する5。あとは接続ユーザ名などの設定だが、これはLaradockの.envファイルで確認した情報と一致しているかを確認するだけで良い。十中八九一致しているはずである。一致していなければ、Laradockの.envファイルのユーザ名などに合わせたほうがいいだろう。
ちなみにこの段階で、試しにphp artisan migrate
してみるとよい。Connection refusedとエラーが発生するはずだ。発生しないのであればこれ以降の作業は必要ない。Laravelのプロジェクト作成をがんばっていただきたい。それはLaravelが最新のMySQLの認証方式に対応したということだから。
エラーが出るなら以降の作業が必要となる。
まずは一旦workspaceから抜ける。exit
でターミナルに戻ろう。
ターミナルに戻ったら、今度はdocker-compose exec mysql bash
でmysqlサービスにログインする。
ログインしたらmysql -u root -p
コマンドを入力、rootユーザでmysqlにログインする。パスワードはLaradockのMySQLの設定にあったROOT_PASSWORDである。
rootでログインしたら、先にも紹介したQiitaの記事にある、認証方式の変更を行う。
https://qiita.com/ucan-lab/items/3ae911b7e13287a5b917
SELECT user, host, plugin FROM mysql.user;
で現在の認証方式を確認- Laradockで接続に使うユーザの認証情報を変更する
- 再度
SELECT user, host, plugin FROM mysql.user;
で認証方式が変更されていることを確認
認証情報の変更はALTER USER 'default'@'%' IDENTIFIED WITH mysql_native_password BY 'secret';
となる。defaultやsecretの部分はそれぞれの環境に合わせて変更して欲しい。この記事ではLaravelからMySQLに接続するユーザはdefaultでパスワードはsecretになっているので、こういうコマンドになる。
設定ができたらexitでmysqlから抜け、再度exitを行いmysqlサービスから抜ける。
念の為、docker-compose restart mysql
でmysqlサービスを再起動しておく。
それが終わればdocker-compose exec workspace bash
でworkspaceにログイン、php artisan migrate
が実行できるか確認して終了である。今度はエラーが出ることなくNothing to migrate.
となるだろう6。
解決策が分かってしまえば、Dockerを使っているという状況を考えなければ非常に単純な問題であった。そう、単にMySQLで使う認証方法を変えればよいだけだったのである。それが生半可な知識を元にDockerを使ったりするから、どこをどうすればよいのかがわからなくなり、盛大に深みにはまる結果となった。
偉そうに初学者向けに講釈をたれているわりに、私もこんな感じでドハマリするわけである。まったくもって偉そうなことを言えた義理ではない。
今回のハマり具合から得られた教訓としては、自分が何をやっているのか理解できないのにコマンドを入力すべきではないということだろう。Dockerよくわからない、Laravelもよくわからない、でも急がないと焦ってしまったのが敗因だ。結果、余計に時間がかかっただけだった。
そのハマった時間を無駄にしないため、こうして記事を書いている。
問題にでくわしたときのアプローチとして、いちばん大事なのは「原因がどこにあるか」である。うまくいかない原因がどこにあるかわからないまま対処するのがもっとも悪手である。本記事においては、「Laravelが最新のMySQLの認証方式に対応していなかった」が原因である。これをどうすれば解決できるのかに注目すべきだった。
そしてもう1つ、複雑な環境で問題解決をしようとしないというのもまた大事である。今回の件で説明すると、私がDockerとLaravel、ともに中途半端な知識しか持ち合わせていないものをかけ合わせた状態で対処したのがまずかった。もっともLaravelを簡単に使うためにLaradockを使っているわけだから、これ以上単純にはできなかっただろうけれど。しかし、LaradockでLaravel本体とMySQLがコンテナ的に異なるコンテナで動いている状態でなければ、もっと解決に早くたどり着けていた可能性はある。
何がいいたいかと言うと、シンプルイズベストなのだ。初めて使う技術やプロジェクトは、それ単体だけでどうやって動いているのかを把握すべきなのである。そうしないと、どこが原因でうまくいっていないのかの切り分けが難しいからである。特にしっかりとした知識のない分野がいくつもかけ合わさっていると、問題の切り分けができずより深みにはまることとなるだろう。
はじめてつかうものや、中途半端な理解のものをやるときには、できる限りシンプルな形で実行するのが一番である。今回の具体例は、その教訓を伝えるのにちょうどよい材料だろう。
-
JavaScriptなどでもまったく同じ状態である。そもそもプログラミングは最初の環境構築が一番難しいと思う。 ↩︎
-
気をつけても気づいたらハマっているのがこの罠のこわいところである。だいたい詳しく理解していない分野について起こりやすい。 ↩︎
-
いい加減入力するのがめんどくさいのでaliasを設定したほうがいいかもしれない。そう思う程度には何度も入力し、微妙にタイポしてイライラを募らせる結果となってしまった。 ↩︎
-
本題ではないので。すでに脱線気味であるからして、細かいコマンドオプションの意味やらは自分で調べて欲しい。 ↩︎
-
docker-compose環境下ではサービス名でアクセスできるからである。そもそもworkspaceのローカルホストにはmysqlのサービスが動いていないので、このままでは動かない。ドキュメントにもそう書いてある。 ↩︎
-
ちなみにいちいちログインしなくても
docker-compose exec workspace php artisan migrate
としてもよい。結果は同じである。 ↩︎