Herokuに本番環境とステージング環境を構築する(Rails5、MySQL5.7)

# 初めに
HerokuにRailsアプリケーションを以下要件で構築したい。

* 本番環境とステージング環境の様に複数環境を用意したい
* RailsアプリがGit管理ルートではなくサブディレクトリに配置されている
* JawsDB（MySQL5.7）アドオン利用
* DBテーブルの文字コードや照合順序を指定したい
* DB migrateをデプロイ毎に自動化したい

# 前提
* Herokuアカウント作成済み
* Heroku CLIインストール済み
* Gitクライアントインストール済み
* Gitリポジトリ作成済み
* 動作するRailsアプリが既に存在する
* MacなどUnixコマンドラインが動作するクライアントで操作

## ディレクトリ構成
Dockerでローカル動作環境を用意しておりRailsアプリはサブディレクトリに配置されている。

````bash
├── .git
├── .gitignore
├── myapp (←サブディレクトリにRailsアプリ)
│   ├── Gemfile
│   ├── Gemfile.lock
│   ├── app
│   ├── （略）
├── mysql
├── docker-compose.yml
```

# 手順
## Heroku上でアプリ作成

まずコマンドライン上でHerokuにログインする。

```bash
 % heroku login
```

* 例としてrails-[環境名]というアプリ名で作成していく。


ステージ環境向けアプリ作成(staging)


```bash
 % heroku create rails-staging --remote staging
```

本番環境向けアプリ作成(prod)

```bash
 % heroku create rails-prod --remote prod
```

gitのリモート情報が追加されている事が確認出来る。

```bash
% git config --list  
remote.staging.url=https://git.heroku.com/rails-staging.git
remote.staging.fetch=+refs/heads/*:refs/remotes/staging/*
remote.prod.url=https://git.heroku.com/rails-prod.git
remote.prod.fetch=+refs/heads/*:refs/remotes/prod/*
```

以降 --app 指定でそれぞれ環境を構築していくのが基本となる。

## MySQLアドオン追加

MySQL5.7を利用したい場合はJawsDBを利用する。

```bash
  % heroku addons:create jawsdb --app rails-staging
  % heroku addons:create jawsdb --app rails-prod
```

## DB接続情報設定[^1]

[^1]: Rails5.2のcredentials:editで設定も可能だがHerokuの場合は環境変数DATABASE_URLを使った方がシンプルな気がする。

configを確認するとDB接続情報が確認出来る。


```bash
% heroku config --app rails-staging
JAWSDB_URL: mysql://ユーザー名:パスワード@ホスト名:3306/DB名
```

表示された情報を元にRails向けにDB接続情報を設定する。
以下部分のみ書き換えた情報を設定する。
`mysql:// →　mysql2://`

```bash
% heroku config:set DATABASE_URL=mysql2://ユーザー名:パスワード@ホスト名:3306/DB名 --app rails-staging
```

本番環境にもDB接続情報を設定する。

```bash
% heroku config --app rails-prod
JAWSDB_URL: mysql://ユーザー名:パスワード@ホスト名:3306/DB名
% heroku config:set DATABASE_URL=mysql2://ユーザー名:パスワード@ホスト名:3306/DB名 --app rails-prod
```

## 文字コード、照合順序をテーブル単位で指定

JawsDBではDBのデフォルト設定が以下となっている。[^2]

[^2]: my.cnf設定不可でアドオン追加したタイミングで空のDBも作成されている。

|文字コード|照合順序|
|:-:|:-:|
|utf8|utf8_unicode_ci|

変更したい場合はRailsアプリのmigrateファイルを直接編集しテーブルデフォルトの文字コード、照合順序指定を追記する。
例えばUsersテーブルを作成する場合、以下ファイルを編集する。
`myapp/db/migrate/2018XXXXXXXXXX_create_users.rb`


下記で指定する場合。

|文字コード|照合順序|
|:-:|:-:|
|utf8mb4|utf8mb4_general_ci|


```ruby:2018XXXXXXXXXX_create_users.rb
 create_table :users, options: 'DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci' do |t|
```

テーブル毎に指定を追記する。


## Procfile作成

用意しなくても動作するがデプロイ時にHerokuから警告メッセージが出力されるのでProcfileを作成しておく。
Railsアプリのディレクトリ位置に作成。

```bash
% vi /myapp/Procfile
```

同時にRelease Phaseという機能でHerokuへのデプロイ毎にDB migrateが動作する様にしておく。

```bash:Procfile
 release: bundle exec rake db:migrate
 web: bundle exec rails server -p $PORT -e $RAILS_ENV
```

ここまでの設定変更内容をgit commitしておく。

```bash
% git add .
% git commit -m "modify migrate files, add Procfile"
```

## 環境変数の追加

必要に応じて環境変数を追加する。

例）Timezone

```bash
% heroku config:add TZ=Asia/Tokyo --app rails-staging
% heroku config:add TZ=Asia/Tokyo --app rails-prod
```


## Herokuへデプロイ

Railsアプリのディレクトリを指定してデプロイする。[^3]

[^3]: ディレクトリ指定無しでpushしてもRailsアプリが読み込まれないので動作しない。

```bash
% git subtree push --prefix myapp staging master
% git subtree push --prefix myapp prod master
```

## 初回デプロイ時に設定される環境変数を変更

Heroku側で用意される環境変数は初回デプロイ前に追加していても上書きされる様なので必要に応じて後から変更する。

LANG等

```bash
% heroku config:set LANG=ja_JP.UTF-8 --app rails-staging
% heroku config:set LANG=ja_JP.UTF-8 --app rails-prod
```

以上でステージング環境、本番環境の構築完了。