Railsの本番環境を作る

## 概要
Railsの本番環境を作る手順です。

## 環境
- Ubuntu20.4 (vagrant)
- PostgreSQL12.4
- Rails5.2

## 手順

#### アセットファイルのプリコンパイル

アセットファイルをプリコンパイルします。JavaScriptsでコードを書いている場合、プリコンパイルでYarnが使われます。Yarnがインストールされていなければ、Yarnがありませんというエラーメッセージが表示されますので、事前に、Yarnをインストールしておく必要があります。
```
$rails assets:precompile RAILS_ENV=production
```

>（トラブルシュート）
>このようなエラーが出てきました。対応方法はメッセージにある通りです。ハーモニックモードを有効にする設定場所は、config/production.rbです。
>
>To use ES6 syntax, harmony mode must be enabled with Uglifier.new(:harmony => true).  （訳）ES6 構文を使用するには、Uglifier.new(:harmony => true) でハーモニー モードを有効にする必要があります。

アセットファイルを削除するときのコマンドです。public/assetsのディレクトリが削除されます。
```
$rails assets:clobber
```

#### database.ymlの編集

database.ymlのproduction項目を本番用に編集します。ここで重要なのはusernameとpasswordです。本番環境なので、セキュリティを上げるために、database.ymlに直接記述するのではなく、環境変数に記述する方がいいでしょう。

環境変数を設定するために、Railsにはdotenvというgemが使われることが多いようです。dotenvを利用する場合は、.envファイルに環境変数を記述します。production環境でも、development環境と同じusername、passwordを指定することはできますが、変えた方がセキュリティ的にはいいでしょう。database.ymlで設定するusernameとpasswordは、OSにログインするときの認証情報ではなく、PostgreSQLにログインするときの認証情報です。

#### PostgreSQLでロールを作成

PostgreSQLに本番用のログイン認証を行うロールを作成します。development環境とproduction環境とで、同じユーザーでログインするのであれば、改めてロールを作成する必要はありませんが、それぞれ異なるロールでログインするのであれば、production用に新規でロールを作成する必要があります。

ロールを作成するとき、オプションでパスワードを指定することを忘れないでください。指定し忘れても、alter roleでパスワードを後から設定することはできます。また、drop roleして、再度、create roleしてもどちらでもOKです。

ロールにはSuperuserの権限を付与してください。Superuserだけでいいです。（注：状況に応じてにはなります）権限の付与は、alter roleで行えます。SuperuserでないとRailsの起動時にエラーになりました。

PostgreSQLへのログインはデフォルトでpeer認証で認証されるようになっています。peer認証で認証させるのであれば、OS側にもロールと同じ名前のユーザーを作成しておく必要があります。パスワードまでは同じにしておく必要はありません。

パスワード認証にするのであれば、OS側にロールと同じ名前のユーザーを追加する必要はありません。その代わり、pg_hba.confに追加したロールの認証設定を１行追加してパスワード認証を有効にする必要があります。

#### データベースを作成する

本番用のデータベースを作成します。
```
$rails db:create RAILS_ENV=production
```

PostgreSQLにログインして、本番用のデータベースが作成されていることを確認します。postgresユーザーでログインしても、本番用のロールでログインしても、同じように表示されます。本番用のロールでログインした後、テーブル一覧を表示させると、当然、この時点では何のテーブルも表示されていません。
```
$sudo su postgres
$psql -d プロジェクト_production
#\l

$psql -U ロール名 -d データベース名
#\l
#\dt
```

#### テーブルを作成する

つぎのコマンドを実行すると、テーブルがありませんといったメッセージが表示されます。マイグレーションの一覧が、すべてdownされた状態で表示されるわけではありません。
```
$rails db:migrate:status RAILS_ENV=production
```

マイグレーションファイルを本番用に流します。エラーなくすべてのマイグレーションファイルが流れてくれるか、少し緊張する瞬間です。正常に流れてくれれば、その後、ステータスを表示すると、マイグレーションの一覧が、すべてupされた状態で表示されます。
```
$rails db:migrate RAILS_ENV=production
$rails db:migrate:status RAILS_ENV=production
```

#### 初期データを更新

seeds.rbに初期データを更新する処理を記述して、初期データが更新します。
```
$rails db:seed RAILS_ENV=production
```

#### 初期データの更新確認

PostgreSQLに本番用のロールでログインして、初期データが更新されていることを確認します。seedsを流していないテーブルは当然、データは入っていないはずです。「あれ？データが入っている！」となれば、誤ってdevelopment環境のデータベースに接続してしまっています。
```
$sudo su - postgres
$psql -d プロジェクト名_production
#\dt
#select * from users;
#select * from テーブル;
```

#### Railsの起動確認

本番環境でRailsが起動されることを確認します。ちなみに「rails s RAILS_ENV=production」では動作しません。
```
#rails s --environment=production
```

## ログ管理

Railsで開発をしていれば、log/development.logは次々と更新されていくことになります。デフォルトではログローテートがされるようになっておらず、開発を続けていくと、ログは際限なく肥大化していくことになります。気が付けばギガ単位にまで膨れ上がっていたなんていったこともあります。

本番環境では、デフォルトのままではログが作成されるようになっていません。もう少し詳しくいえば、ログは作成されるようになっているが、デフォルトの設定で有効になっていないということです。ログを有効にするには、次の環境変数を設定します。
```.env
RAILS_LOG_TO_STDOUT = true
```

この環境変数を設定すればログが作成されるようになるが、ログローテまでは行ってくれるようにはなりません。別途、設定をする必要があります。

ログローテはOSに標準で用意されているcronを使って行うこともできるが、Rails側で行うこともできます。Rails側で行うにはLoggerクラスを使います。

例えば、つぎの設定はこのような意味になります。
- ログファイルの容量が10MBに達したら、つぎの新しいログファイルが作成されいます。
- ログのバックアップファイルの履歴は5個まで保持します。
- 6個目のログが作成されるタイミングで、一番古いバックアップファイルが削除されます。

```config/environments/production.rb
   config.logger    = Logger.new("log/production.log", 5, 10 * 1024 * 1024)
```

> 参考
https://takeda-no-nao.net/programming/ruby/delete-log-files-after-certain-period-of-time/

## その他

開発で作成されたログ、キャッシュファイルもクリアしておきましょう。
```
#rails tmp:clear
#rails log:clear
```