48
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

config/environments/staging.rb はアンチパターン!

Last updated at Posted at 2018-02-22

Rails では、config/environments/*.rb に、実行環境ごとに異なる設定を書けます。

rails new で新規作成すると、以下の3種類が生成されています。

  • production.rb (本番環境)
  • development.rb (開発環境)
  • test.rb (CI環境)

どの環境としてアプリを起動するかは、環境変数 RAILS_ENV で指定できます。

そして、config/environments/*.rb は、独自に追加することができるので、
ステージング環境(本番デプロイ前にテストする環境)の設定を

  • staging.rb

に書いている。・・・というプロジェクトは多いと思いますが、私は staging.rb はアンチパターン だと思います。

なぜ、アンチパターンだと思うのか?

テストは本番と同じコード・設定・環境でするのが基本です。本番と違うものを動かして問題がなかったとしても、それはテストにはならないのです。当たり前ですが。

そのため staging.rbproduction.rb は同一の内容でなければならないはずです。

しかし、別ファイルにしている時点で、同一内容か保証し続けるのは難しいのです。
コードレビューなどでチェックすることも考えられますが、きっと起きます。
「ステージング環境では問題ないのに本番環境では起動すらできない。実は production.rb を修正し忘れていていた」事件が。

代わりにどうすればいいか?

ステージング環境でも production.rb を使いましょう!同じ設定を使うのだから、必ず本番環境と同じ動作になります。

もちろん、ステージング環境と本番環境ではホスト名やAWSアカウントなどが異なることも多く、その差異を何らかの方法で吸収しなければなりませんが、大きく分けて、

  1. 差異をインフラ層で吸収する
  2. 環境変数で設定する

の、2種類の方法があります。

1. 差異をインフラ層で吸収する

例えば、本番とステージングでSMTPサーバーのホスト名が異なるなら、ステージング環境の /etc/hosts に以下のような設定を追加します。

# /etc/hosts
#
# 本番環境のSMTPサーバーのホスト名が smtp.xyz.com で、
# ステージング環境のSMTPサーバーのIPが192.168.2.18のとき、
# ステージング環境のRailsサーバーに以下のような設定を追加。

192.168.2.18 smtp.xyz.com

こうすることで、このサーバー内では(アプリケーションのコードは変えていないのに) smtp.xyz.com で本番ではなくステージング環境のSMTPサーバーにアクセスするようになります。サーバーの台数が増えていくと/etc/hostsよりDNSで管理した方がいいかもしれません。

もちろん、インフラ層が原因で別の問題が起きる可能性も生じます。例えば「/etc/hosts のIPを間違えて別のサーバーに接続しちゃった!」とか。しかし、経験上、インフラの設定ミスが起きる頻度は、アプリの不具合よりずっと低い。

ただし、今後のDocker化などを見据えると「2. 環境変数で設定する」の方が発展性があるかもしれません。

2. 環境変数で設定する

例えば、本番とステージングでSMTPサーバーのホスト名が異なるなら、それぞれ SMTP_HOST という環境変数にホスト名を指定しておくようにします。

# config/environments/production.rb
Rails.application.config do

  ...

  # 本番とステージングで、SMTPサーバーのホストが異なる場合の例:
  config.action_mailer.smtp_settings = {
    address: (ENV['SMTP_HOST'] || raise '環境変数 SMTP_HOST が定義されていません'),
    port: 2525
  }

  ...

end

なお、環境変数を使う方法には、アプリのDocker化がしやすくなるおまけのメリットがあります。

従来のオンプレミス環境では、サーバーのホスト名やポート番号は、基本的に変化しないものでした。しかし、Kubenetesなどの環境では、ホスト名やポート番号は動的に変化するので、外部からアプリに設定を注入する必要があります。その注入方法としては環境変数を使うものが多いようです。

また、SaaS開発の方法論である The Twelve-Factor App でも、「設定を環境変数に格納する」と明確に指定されています。

staging.rb が許容される場合

ごく小規模な、他のサーバーとほとんど通信しないようなアプリで、Docker化の予定も無いということであれば、staging.rb を書くのが手っ取り早いかもしれません。

しかし、私としては最初から production.rb と環境変数を使うことをオススメします。

48
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?