Heroku × nginx × MySQL × Laravel × Reactで本番環境を構築する

おはようございます！
最近知人のエンジニアと共同開発を行っていて、その際に本番環境の構築を担当したので、ざっくりとした手順を備忘録としてまとめることにしました！
この記事が似たように環境構築を行う方の参考になれば幸いです💦

## 前提
- 開発環境の構築が終了していること
開発環境のディレクトリはdockerで作成し、以下のディレクトリ構成で構築しています。
```
アプリ名
 ├── README.md
 ├── infra
 │   ├── mysql
 │   ├── nginx
 │   └── php
 ├── docker-compose.yml
 └── src（laravelのソースコード）
     ├── app
     ├── ・・・
```

## 使用技術
- nginx1.20
- MySQL8.0.28
- php8.1.4
- Laravel8.83.7
- node17.9.0
- React17.0.2

## なぜheroku?
- 無料プランが存在するから
- 構築が容易なため

## 構築手順
herokuアカウントは作成ずみと仮定しております。
もしアカウント登録がまだの場合には登録をお願い致します。

### herokuアプリの作成
herokuにログイン後、任意のアプリ名を入力し、`create app`をクリック

### Procfileの作成

#### Procfileとは
herokuの起動時に実行するコマンドを指定するファイル。ここにコマンドを書き込むことでheroku内で起動させるwebサーバーの指定などができる。

参考

https://devcenter.heroku.com/ja/articles/procfile

```:Procfile
web: vendor/bin/heroku-php-nginx -C heroku_nginx.conf public/
```

phpとnginxを使用するため、`web: vendor/bin/heroku-php-nginx`と記載します。
`-C ファイル名.conf`で参照したいnginxの設定ファイルを指定することができます。（Procfileと同じ階層内にない場合には、Procfileからみた、設定ファイルのパスを記述してください。例： `-C ./heroku/production/nginx.conf`）

ドキュメントルートを指定する場合には、**末尾に**ドキュメントルートに指定したいディレクトリ名を追記してください。
今回はpublicディレクトリ配下を参照したかったので`public/`と記載しました。

参考

https://devcenter.heroku.com/ja/articles/custom-php-settings

### nginxの設定ファイルを作成
Procfileで指定した位置に、設定ファイルを記述します。

```conf:heroku_nginx.conf
location / {
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    rewrite ^(.*)$ /index.php$1 last;
}
```

### MySQLの導入
Herokuでは、デフォルトで使用できるDBはPostgreSQLになっているので、アドオンを追加してMySQLを使用できるようにする必要があります。
使用するMySQLのバージョンが８.０のため、今回はJawsDBを使用します。

```:terminal
heroku addons:create jawsdb:kitefin -a herokuのアプリ名 --version=8.0.28
```

参考

https://dhate.hatenablog.com/entry/2019/12/08/012312

### Buildpacksの設定
rubyとは違って、herokuでphpやnodeを使用するためには、Buildpacksで設定する必要があります。

herokuアプリの管理画面に移動しSettingsを開いて、`Add buildpack`をクリックしてモーダル画面から以下のビルドパックの追加を行ってください。
- https://github.com/timanovsky/subdir-heroku-buildpack
- heroku/node.js
- heroku/php

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702700/4c44f5e1-1af9-1a8a-4641-60da45c08359.png)

※注意点
`https://github.com/timanovsky/subdir-heroku-buildpack`だけは必ず**一番初め**に追加してください。
Buildpacksは入れた順番も関係しているみたいで、これを初めにインストールしないと、デプロイ時にエラーが発生します。（自分はこれで結構はまりました。。。）

### 環境変数の設定
herokuアプリの管理画面に移動しSettingsを開いて、環境変数を設定する。

#### DBの設定
DBの設定情報は、JawsDB上にあるのでそちらを確認してください。
JawsDBに移動するには、herokuアプリの管理画面、Overviewから移動できます。

JAWSDB_URL = mysql:から始まるURL
DB_CONNECTION=mysql
DB_USERNAME=◯◯◯◯
DB_PASSWORD=△△△△
DB_HOST=□□□□
DB_DATABASE=××××
DB_PORT=3306

#### その他の設定
APP_KEY = 開発環境の.env参照
APP_URL = herokuで作成したアプリのURL
PROJECT_PATH = laravelのソースコードが入っているディレクトリ名（今回の例だとsrc/が該当）

### ローカルリポジトリにHerokuアプリ用のリモートリポジトリを登録

```:terminal
heroku git:remote -a {アプリ名}
```

### herokuにソースコードをpush

```:terminal
git push heroku master
```

※ master以外のブランチでpushする場合には、

```:terminal
git push heroku ブランチ名:master
```

### DBのマイグレーションを実行

```:terminal
heroku run php artisan migrate
```

### その他設定

https://zenn.dev/karaageeeee/articles/b6f201d61a2f81

の`URLをHTTPSで生成させる`と`HttpをHttpsにリダイレクトさせる`を行う。

### 画面確認
herokuアプリのURLを開いて、想定した画面が表示されていたら環境構築完了！
もしエラーが出てしまったら、都度エラーをみて対応する。（開発環境の差異によって、この手順を踏んでもエラーが発生する可能性があります。staging環境の構築も行うつもりなので、その際エラーが発生した場合にはこの記事に追記していきます。）

### 最後に
1からOS入れて、webサーバー入れて、DB入れて、、、
などをしなくて良いのでかなり手早く環境構築できました。（結構ハマったと思ったのですが、3時間くらいで終了しました。）
やっぱheroku楽でいいですね！

とはいえ、無料プランだと30分アクセスがないとdynoがsleepしてしまうので、そこは定期的にアクセスする機構をGASなりheroku schedulerなりで実装する必要がありそうです！

herokuアプリのdynoをsleepさせない方法は以下の記事に書いてありますので、よろしければこちらもご一読いただけますと幸いです🙇‍♂️

https://qiita.com/koudai_kumazaki/items/d2489a44dc76948735af

最後になりますが、この記事を読んでご自身の環境構築に役に立ったと感じていただけた場合には、LGTMをいただけますと幸いです。（執筆モチベーションが上がりますのでw）