はじめに
表題の通りです。
こちらの本を使ってlaravel学習し、Webアプリを作成しましたが、デプロイないまま終わってしまったのでデプロイの手順を調べながら進めます。
構成
- IDE:cloud9
- フレームワーク:laravel
- 言語:PHP
- DB:MySQL
前提
- herokuへのアカウント登録は済んでいる。
- GitHubへのソースアップは行っている。
デプロイの設定
herokuはGitHubと繋げてそのまま公開ができるのでまずはその設定をします。
アプリ一覧より、Newで適当なアプリ名で作成。
作成したアプリを選択し、[Deploy]タブでGitHubの設定を行います。
さらにスクロールし、自動デプロイの設定もしておきます。
今回はもうコミットが済んでしまっているGitHubを使うので手動デプロイしましょう。[Deploy Branch]ボタンを押下します。
エラー1つ目(ビルドパッケージの選択)
-----> Building on the Heroku-20 stack
-----> Determining which buildpack to use for this app
! No default language could be detected for this app.
HINT: This occurs when Heroku cannot detect the buildpack to use for this application automatically.
See https://devcenter.heroku.com/articles/buildpacks
! Push failed
言語が検出できなかったので、ビルドパッケージを指定してくれと言われる。通常laravelのプロジェクトを普通に作っていればおそらく検出可能です。理由は後述しますが、とりあえず言われた通りに[Setting]タブよりビルドパッケージをphpで指定します。
エラー2つ目(herokuに必要なものの再配置や新規作成)
-----> Building on the Heroku-20 stack
-----> Using buildpack: heroku/php
-----> App not compatible with buildpack: https://buildpack-registry.s3.amazonaws.com/buildpacks/heroku/php.tgz
! ERROR: Application not supported by this buildpack!
!
! The 'heroku/php' buildpack is set on this application, but was
! unable to detect a PHP codebase.
!
! A PHP app on Heroku requires a 'composer.json' at the root of
! the directory structure, or an 'index.php' for legacy behavior.
!
! If you are trying to deploy a PHP application, ensure that one
! of these files is present at the top level directory.
!
! If you are trying to deploy an application written in another
! language, you need to change the list of buildpacks set on your
! Heroku app using the 'heroku buildpacks' command.
!
! For more information, refer to the following documentation:
! https://devcenter.heroku.com/articles/buildpacks
! https://devcenter.heroku.com/articles/php-support#activation
More info: https://devcenter.heroku.com/articles/buildpacks#detection-failure
! Push failed
phpのビルドパッケージにしては、以下がないと言われています。
- HerokuのPHPアプリには、のルートに「composer.json」が必要です。
- ディレクトリ構造、またはレガシー動作の場合は「index.php」。
私のGitHubリポジトリの構成は明らかに前者を満たしていません。
/
├──.c9
├──cms
│ └──public
│ │ └──index.php
│ └──composer.json
├──.git
├──.gitignore
└──README.md
なぜcloud9部分からgit管理してしまったのか。
素直に構成を変えます。(ローカルで.gitを削除し、cmsの下に作り直せばいいのですが、リモートリポジトリとの差が大きくなり、マージで何か起きそうだったのが怖くて新しいリモートリポジトリを作り、そちらに.gitの階層を改めたソースをコミットしました。)
/
├──public
│ └──index.php
├──composer.json
├──.git
├──.gitignore
└──README.md
次にindex.php
エラーからはよくわからなかったですが、laravelのディレクトリ構成により、public配下にあることはherokuに伝える必要があると思われるのでエラーを検索。
以下がヒットしました。
https://devcenter.heroku.com/articles/custom-php-settings#setting-the-document-root
上記のリンク先の通り、コマンドで必要なファイルが作られますが、手作りで配置しても問題ないと思います。
web: vendor/bin/heroku-php-apache2 public/
ルート直下に格納しコミットしpush。
先ほど自動デプロイ設定をしているので自動でデプロイが走ります。
通りました。
なお、1つめのエラーは、この2つ目の対応をした状態でしたら発生しなかったと思います。
エラー3つ目(laravelの復号化:APP_KEYの設定)
まだ色々設定していませんが、まずはWebサーバが動いていることの確認をします。
herokuアプリへアクセス:https://my-laravel-project-heroku.herokuapp.com/
500はサーバエラーですが、レスポンスコードを返せているということはWEBサーバは動いています。
想定は、心当たりはDB設定が未だったのでDB接続時にエラーが出ることでしたが、TOPページでDB接続は行っていないので別段の問題があるようです。
ここで初めて知りましたが、laravelは暗号化されており複合には.env
ファイルのAPP_KEY
が必要らしいです。
開発時は、comporserを実行しましたが、このAPP_KEYは自動で生成されていたようです。
$ composer global require "laravel/installer"
このキーがないと暗号化されたままでheroku側で復号化できないので、herokuにも設定する必要がありますので、まずは.envファイルからAPP_KEYをコピーします。
[Settng]タブにてherokuのConfigを開きます。
KEY:VALUE形式なので、左側に「APP_KEY」、右側にコピーした値を入れます。
※なお、envファイルをcommit対象にしてherokuに持ち込んで使う方法もあるようですがセキュア情報がpublicファイルになるのは大丈夫なんでしょうか。publicじゃないgitで管理しているのであれば問題ないと思います。
エラー4つ目(データベース追加と設定)
先ほど出たTOP画面で試しに、ログイン情報を入れてDB接続を発生されたところ500エラーになりました。
herokuでは明らかにDB設定をしていませんので想定通りのエラーです。
では、これを解消していきます。まずはデータベースは[Resource]タブから登録します。
[ClearDB MySQL]の[Ignite]プランがFreeなのでこちらを選択します。(ただし利用するにはクレジットカードの登録は必要です)
接続するアプリを聞かれるので、入力します。(私の場合、my-laravel-project-heroku)
問題なければ、[Submit Order Form]ボタンを押下
追加されました。
なお、ここで[Settings]タブのConfigにはCLEARDB_DATABASE_URL
が自動的に追加されます。
laravelだとCLEARDB_DATABASE_URL
ではなく、DATABASE_URL
で設定を読んでいるんですよね。。
このままだと参照できないので、[Settings]の方を変えます。
変更の方法は色々あると思いますが、今回は、キーにDATABASE_URL
にバリューにCLEARDB_DATABASE_URL
と同じ値を入れる形としました。
DATABASE_URL
以外でも.envに定義している環境設定があるのでCLEARDB_DATABASE_URL
の情報を元に追加していきます。
mysql://(ユーザー名):(パスワード)@(ホスト名)/(データベース名)?reconnect=true
なお、herokuではPHP側を変える設定が説明されていますが、laravelのローカル開発時(Cloud9では.envを読むので)動作と合わなくなってしまうのでこの手段は取っていません。
https://devcenter.heroku.com/articles/cleardb#using-cleardb-with-php
エラー5つ目(マイグレーション)
まだ中身がないので、残るはマイグレーションをやっていきます。
ここまでCLIを使わず、画面上で設定してきましたが、流石にlaravelの機能であるマイグレーションをheroku画面で実施することができないのでCLIを使います。
Cloud9にherokuのインストール
ローカルにherokuを入れているのでそちらを使っても良かったのですがせっかくなのでcloud9からやってみます。
$ source <(curl -sL https://cdn.learnenough.com/heroku_install)
$ heroku -v
heroku/7.56.1 linux-x64 node-v12.21.0
Cloud9でマイグレーション
まずはログイン(MFA有効だとcloud9上でうまくいかないので無効にしました)
$ heroku login -i
heroku: Enter your login credentials
Email: {メールアドレス}
Password: ***********
Logged in as {メールアドレス}
ログインできたらアプリを指定してrunを実行します。
$ heroku run "php artisan migrate" -a my-laravel-project-heroku
Do you really wish to run this command? (yes/no) [no]:
> yes
Command Canceled!
なんでやねん。
タイプミスでyse
通ったのでよくわからないです。y
でもいけました。
$ heroku run "php artisan migrate" -a my-laravel-project-heroku
Running php artisan migrate on ⬢ my-laravel-project-heroku... up, run.5001 (Free)
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) [no]:
> yse
Migration table created successfully.
ついにDBアクセス含めた画面が出ました。
これは、アカウント登録した後の画面です。右上にDB登録されたアカウント名が取得され表示されています。
テストデータを投入する
せっかくなのでテストデータを入れます。
$ heroku run "php artisan db:seed --class='BooksTab
leSeeder'" -a my-laravel-project-heroku
In BooksTableSeeder.php line 15:
Class "Faker\Factory" not found
もう、すんなりうまく行くことがない。
同じ事象がたくさん出ているようで、こちらを参考にさせていただきました
解決方法を読んで納得しましたが、テストデータ入れるためのものをrequire
に入れるのはよくないですね。
このエラーは正しいと思いますが、今回はデモ的にデータが欲しいのでこの通りにします。
/cms/composer.jsonを以下のようにしましました。(fakerはfzaninotto
のフォーク)
この後は、composer update
をし、commitとpush。
デプロイが終わったところを見計らい、再実行したところうまくいきました。
$ heroku run "php artisan db:seed --class='BooksTableSeeder'" -a my-laravel-project-heroku
Database seeding completed successfully.
【余談】
テストデータは挿入されたのですが、fakerで画像ファイルが作成されず、データベースにはファイル名だけ登録されているため画像がリンク切れとなりました。
herokuのサーバ内に入って確認しましたが、upload/配下はCloud9環境でテストデータを作成しGitHubにあげたファイルのままです。
Webアプリからも画像アップできるUIがあったので試してみましたが、419エラーとなりました。
fakerではなくherokuでは画像アップロード自体できないように見えました。
試しにherokuサーバにbash出入り、画像がアップされる先に権限をつけてみました。
UI操作から419エラーは出なくなりましたが、画像はアップされていませんでした。
// heroku内へ
$ heroku run {アプリ名}
// 画像アップに関係するフォルダの権限を付与
$ chmod a+wrx public/upload
$ chmod a+wrx public
herokuに画像をアップし続けて負荷をかける可能性を考えると正しい挙動な気がします。
GitHubからアップした画像ファイルは許容されているので力技ですが、テーブル内の値をupload/配下のファイル名に合わせましたが、herokuにおいてはUIからのアップロードは不可となりました。
$ mysql -u {DB_USERNAME} -h {DB_HOST} -p
>>> use {DB_DATABASE}
>>> update books set item_img = "f7a773e1290ff18932af806d9a0134c5.png" where item_img = "3c141ed179e0b41b44c864da732d0a49.png";
デプロイ完了
成果物はこちらにまとめました。
おわりに
さっと終わらせるつもりでしたが、時間かかってしまい疲れました。
この本、環境構築周りでの気遣いはものすごくありましたが、
途中から画像の更新処理や削除処理がなかったり、デプロイがないので注意ですね。。
成果物
あとで変えると思うのでタグも置いておきます。
画像周りは前述の通り何もかもおかしいです。
GitHub:https://github.com/c3drive/my_laravel_project_heroku
GitHub執筆時点ソース:https://github.com/c3drive/my_laravel_project_heroku/releases/tag/1.0
heroku:https://my-laravel-project-heroku.herokuapp.com/
ーメールアドレス:test@example.com
ーパスワード:test00000
備忘
$ heroku run {アプリ名}
$ mysql -u {DB_USERNAME} -h {DB_HOST} -p