Laravel × PostgreSQL をHerokuへデプロイする

## ■はじめに

Laravelで作成したWebアプリケーションをHerokuの本番環境にデプロイするまでの手順をまとめます。Laravelを用いるとドキュメントルートの設定だったり、マイグレーションの設定が必要なので注意が必要です。環境変数の設定で非常に手こずりました。  
[Herokuの推奨DBがPostgreSQL](https://jp.heroku.com/postgres)だったのでDBはPostgreSQLを用います。[拡張機能](https://elements.heroku.com/addons/heroku-postgresql)もサポートされている様。  
また、手軽にstaging/production環境を作成できる[Heroku Pipeline](https://devcenter.heroku.com/articles/pipelines)を利用します。  
Webアプリケーションの開発自体はVirtualBoxにCentOSを立てて行います。

## ■構築環境
- Heroku
- Laravel 5.7.28
- PostgreSQL

## ■事前準備
### Heroku CLIのインストール

- 基本ブラウザのGUIでやる想定なので念のためインストール

```sh:bash
$ brew install heroku/brew/heroku
$ heroku --version # 確認
```

### Herokuのアカウント作成

- [こちら](https://jp.heroku.com)からアカウントを作成する
- クレジットカード情報を入力すれば無料のdyno時間が**550時間→1000時間**になるので、登録しておいた方が良い

### Herokuへログイン

```sh:bash
$ heroku login
```

## ■Heroku側の設定

### アプリの作成

- staging環境用とproduction環境用のアプリをそれぞれ作成する

### Heroku Pipelineの設定

- New > create New Pipeline を押しパイプラインを作成
- 作成したパイプラインのstaging,productionにそれぞれのアプリを割り当てる
- それぞれのアプリで**Github連携**をする(staging環境は**developブランチ**,production環境は**masterブランチ**)
- staging環境は**自動デプロイ**の設定をすることで、developへマージされると自動でアプリがデプロイされる
- **Review Apps**を有効にすることでPR作時に確認用のアプリケーションが作成される

### Review Appsの設定

1. REVIEW APPS > Enable Review Appsを押す
2. parent appにstagingのアプリを選択し`Create an app.json File`を押す
3. 後で直接編集すれば良いので、app.jsonの設定値を入力する画面はスルーでOK
4. 今回は下記の様なapp.jsonを用意する

```json:app.json
{
    "addons": [
      "heroku-postgresql"
    ],
    "buildpacks": [

    ],
    "description": "review app",
    "env": {
        /* staging環境の環境変数 */
    },
    "formation": {
    },
    "name": "<アプリ名>",
    "scripts": {
      "postdeploy": "php artisan migrate --force"
    },
    "stack": "heroku-18"
  }
```

### PostgreSQLのAdd-onの追加

1. ブラウザでHerokuにログイン
2. アプリ名 > Resources > Add-ons で`Heroku Postgres`を検索
3. `Hobby Dev -Free`を選択

## ■ソース側の設定

### Webアプリケーションの作成

- [Laravel 開発環境の構築（CentOS7）](https://qiita.com/koukibuu3/items/300ce50a9acb8674ccf3)を参考にLaravelプロジェクトを作成
- PostgreSQLの導入方法は[CentOSにPosgreSQLの環境構築](https://qiita.com/koukibuu3/items/9a409a1256a8cf02e053)を参考

### Procfileの生成

```config:Procfile
web: vendor/bin/heroku-php-apache2 public/
```

- アプリディレクトリ直下に上記Procfileを生成
- ProcfileはHerokuアプリの起動時に実行されるプロセスを記載する
- ここではApacheの使用の指定と、ドキュメントルートの設定を行う
- Procfileはきちんとコミット対象に含めること


## ■環境変数の設定

- 以下の手順をstaging環境とproduction環境両方のアプリに対して行う

### DATABASE_URLの値を元に環境変数を設定

```sh :bash
$ heroku config:get DATABASE_URL -a <アプリ名>
postgres://<ユーザ名>:<パスワード>@<ホスト名>:5432/<DB名>
```

### Heroku CLIで設定

```sh:bash
# DB種類
$ heroku config:set DB_CONNECTION=pgsql -a <アプリ名>
# ユーザ名
$ heroku config:set DB_USERNAME=<ユーザ名> -a <アプリ名>
# パスワード
$ heroku config:set DB_PASSWORD=<パスワード> -a <アプリ名>
# ホスト名
$ heroku config:set DB_HOST=<ホスト名> -a <アプリ名>
# DB名
$ heroku config:set DB_DATABASE=<DB名> -a <アプリ名>
# APPキー
$ heroku config:set APP_KEY=$(php artisan key:generate --show) -a <アプリ名>

# まとめて設定(その1)
$ heroku config:set DB_CONNECTION=pgsql DB_USERNAME=<ユーザ名> DB_PASSWORD=<パスワード> DB_HOST=<ホスト名> DB_DATABASE=<DB名> APP_KEY=$(php artisan key:generate --show) -a <アプリ名>

# まとめて設定(その2)
$ heroku config:set DB_CONNECTION=pgsql -a <アプリ名> $(heroku config:get DATABASE_URL -a <アプリ名> | awk '{print gensub(/postgres:\/\/(.+):(.+)@(.+):5432\/(.+)/, "DB_USERNAME=\"\\1\" DB_PASSWORD=\"\\2\" DB_HOST=\"\\3\" DB_DATABASE=\"\\4\"", "g")}')
```

### 設定内容の確認

```sh:bash
$ heroku config -a <アプリ名>
=== <アプリ名> Config Vars
APP_KEY:       <APPキー>
DB_CONNECTION: <DB種類>
DB_DATABASE:   <DB名>
DB_HOST:       <ホスト名>
DB_PASSWORD:   <アプリ名>
DB_USERNAME:   <ユーザ名>
```

- 正常な値がAPP_KEYの項目に設定されていないため、ここで生成された<APPキー>を、ブラウザ **(アプリ名 > Setting > Config Vars)** より、設定し直してあげる必要がある
- ここまでやれば、アプリ名 > Open app からアプリを起動することで、無事にLaravelのサンプルページが表示されているはず
- `$ heroku open -a <アプリ名>` でも可

### DBのマイグレーション

```sh:bash
$ heroku run php artisan migrate -a <アプリ名>

# マイグレーションをやり直す場合
$ heroku run php artisan migrate:refresh --seed -a <アプリ名>
```

## ■参考

- [Laravelをherokuにデプロイする(データベースはPostgreSQL)](https://qiita.com/tamappe/items/14a4e6890ecef4d49d1f)
- [Laravel + Heroku + HerokuPostgres でDB設定をサクッと環境変数に突っ込む](https://qiita.com/kamukiriri/items/1c5e17872c2fcefa1678)
- [Heroku Pipelineを使ってみる](https://qiita.com/yo-iida/items/f99566fe4617f848fa39)