ねこものがたり

いちにちいっぽ

Rails.envにstagingを追加するのはよくないと言われるのは何故か整理してみました

このエントリのきっかけ

業務で開発してるRailsアプリケーションにRails.envがたくさんあって、「環境を整理したい」「デフォルトに寄せたい」という話が沸いています。 「それはそう」って思ってしばらく過ごしていたんですが、あるときふと「何故?」って聞かれたら自分は説明できないな、と気付いたので、これを機によく理解しておこうと思いました。 この記事は"備忘録"と言うやつですね!(私の場合備忘録じゃないブログエントリほとんどないですが)

デフォルトのRails.env

デフォルトとRails.envはdevelopment, test, productionです。rails new したらこの3つの環境が備わっています。 それぞれどう言うものかという詳細は productionやdevelopment、stagingという言葉の使い分けについて|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社がまとまっていてわかりやすいと思いました。

productionモード
本番モードで、動作中にソースコードが編集されない前提が取れるため、クラスキャッシュなどをアグレッシブに保持して効率化ができる(config.cache_classesやconfig.eager_load)
静的ファイル配信はRailsサーバーからではなくnginxなどの手前Webサーバーから配信させる前提の設定(config.public_file_server.enabled = false)がされている

developmentモード
起動中にソースコードが編集されてもRailsサーバーの再起動不要で変更結果が反映される(config.file_watcherやconfig.cache_classesの無効化など)
開発者のローカル環境ではいちいちnginxなどを立ち上げなくても良いように、public以下の静的ファイルもRailsサーバーが配信する(config.public_file_server.enabled = true)

testモード
developmentモードに近いが、さらにCIやターミナル前提の設定などが付く(consider_all_requests_local = :stderr)

新しい環境を作る方法

Rails アプリケーションを設定する - Railsガイド

config/environments/staging.rb を作ればstagingができます。 staging.rbの中には必要な設定項目を記載します。

stagingを作らない方がいい理由

Rails が標準として環境追加の機能を備えているのに、どうして「それはダメです」と言う声が多いんだろう? ここから先は私が調べたり、現場で体感したりしたことのまとめです。

そもそもステージング環境とはなんだ

「検証環境」と言う言葉でさもそれらしい認識はしていた私ですが「ちゃんと説明して」と自問してみるとどうやら理解が浅いぞと気付いたので調べてみました。

ステージング環境 (staging environment)がとってもわかりやすかったので拝借します。

できるだけ実際に使うときの状況(本番環境)に似せて作った動作確認用の場所(テスト環境)のこと

できるだけ実際に使うときの状況(本番環境)に似せていると言うのがstagingのポイントのようです。

config/environments/staging.rb でステージング環境を作成するデメリット

上述のように config/environments/staging.rb を config/environments/production.rb と同じ設定内容で作成すると名前は別だけれど設定は同じになります。 では何故ダメなのか?内容同じにすれば本番環境と同じになるならよくない?という気も(ほんの少し)してきました。

でも長期的な運用を考えたときに「設定内容の同期が不確実」と言う懸念点が挙げられます それはつまり、production.rbを変更をしたときstaging.rbも変更しないといけない(逆もまた然り)で、「本当にこの環境は十分本番に似せ切れているのか?」を担保し切れなくなってしまうかもしれません。 本番にリリースして問題ないか確認するためのステージング環境なのに前提が崩れてしまう可能性をはらんでいます。

どのようにステージング環境を用意すると良いか

思い切って(?)ステージング環境もconfig/environments/production.rbを使いましょう。 でもconfig/environments/staging.rbをそのまま使っているだけではそれはただの本番環境なのでステージングになりません。 どうすれば??

本番とステージングで環境で同じにするもの・差分が必要なもの

どうすればいいんだろう整理する為に、何を使い分けると良いのか考えてみると以下のようになるのかなと理解しています。

同じにするもの:基本的に全て

変えるもの:本番と同じにしてはいけない値

本番環境と同じであることを基本として、本番と同じものは使えない値だけを変えると良いようです。 アプリケーション全体で言うとDBの接続先を本番用じゃないDBにする等、config/environments/production.rbファイル以外のconfigの値の方が注意を払わないといけない対象が多いように思います。

config/environments/production.rbを共有しながら値を使い分ける方法

production.rbの設定値を環境変数の参照にすると良さそうです。 rails sに何かフラグを渡せるようにして、それによって参照先も変える方法があります。

まとめ

stagingを追加するのがよくない理由は、要するに本番環境同等の環境の担保の問題だと理解しました。

この記事を書いていて、production.rbの設定でステージング環境も動かすためにも、秘匿情報やAPIやDBの参照先、何かの通知設定など本番と同じにしてないけないこと・分けておきたいことは何かを整理して事故のない運用と品質の担保をしていきたいと思いました。