0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

第34章|今さら学ぶ「環境管理(development / test / production)」

0
Last updated at Posted at 2026-03-04

第34章|今さら学ぶ「環境管理(development / test / production)」

📚 シリーズ目次はこちら → 「今さら学ぶ」シリーズ — はじめに
🗺️ KnowledgeNoteの設計を確認 → 設計マップ

この章でわかること

  • development / test / production — 3つの環境の役割と違い
  • config/environments/ — 環境ごとの設定ファイルの読み方
  • Rails.env — コードの中で環境を判定する方法
  • credentials と環境変数 — 秘密情報の管理方法と使い分け

🏠 たとえ話で掴む「環境管理」

レストランでたとえると、「本番営業」と「仕込み・練習」は同じ厨房でも設定が違います。

本番営業では「本物の食材を使う」「お客さんには失敗を見せない」「会計システムをフル稼働させる」。仕込み中は「食材を無駄にしてもいい」「盛り付けを試行錯誤できる」「会計はスキップ」。

Railsでも同じです。 開発中は素早く動かすための緩い設定、 本番では安全・品質重視の厳格な設定 と、環境ごとに切り替えます。

レストラン Railsの環境管理
本番営業(お客さんあり) production — 実際のユーザーが使う
仕込み・練習(スタッフのみ) development — 手元で開発
衛生検査のシミュレーション test — 自動テストの実行

環境管理とは何か — 技術的な定義

3つの環境

Railsには標準で3つの環境があります。

環境 名前 用途
development 開発環境 手元で開発するとき
test テスト環境 RSpecなどのテスト実行時
production 本番環境 実際にユーザーに公開するとき

RAILS_ENV 環境変数でどの環境で動かすかを指定します。rails server はデフォルトで development、テスト実行時は test、Renderなど本番サーバでは production になります。

3つの環境で何が違うか

設定 development test production
ログレベル debug(詳細) debug info(最小限)
キャッシュ 無効 無効 有効
アセット 都度読み込み 都度読み込み 事前コンパイル
エラー表示 詳細エラー画面 例外を raise カスタムエラーページ
メール letter_opener 実際には送らない 実際に送信
DB名のサフィックス _development _test 本番DB
コード自動リロード あり なし なし
SSL強制 なし なし あり

📁 config/environments/ — 環境別設定ファイル

config/
├── application.rb           ← 全環境共通の設定
└── environments/
    ├── development.rb       ← 開発環境のみの設定
    ├── test.rb              ← テスト環境のみの設定
    └── production.rb        ← 本番環境のみの設定

development.rb のよく使う設定

# config/environments/development.rb
Rails.application.configure do
  # コードを変更しても再起動不要(自動でリロード)
  config.enable_reloading = true

  # エラー時に詳細なスタックトレースを画面に表示
  config.consider_all_requests_local = true

  # キャッシュを無効化(`rails dev:cache` でON/OFFできる)
  config.action_controller.perform_caching = false

  # メールはブラウザで確認(実際には送らない)
  config.action_mailer.delivery_method = :letter_opener_web

  # ログを詳細に出力(SQLも全て表示)
  config.log_level = :debug

  # N+1検出ツール(→ [第24章](https://qiita.com/harapeco-mgn/items/fc2ffbd0035b8f9f3a39))
  config.after_initialize do
    Bullet.enable        = true
    Bullet.rails_logger  = true
  end
end

production.rb のよく使う設定

# config/environments/production.rb
Rails.application.configure do
  # コードの自動リロードをしない(パフォーマンス向上)
  config.enable_reloading = false

  # エラーの詳細をユーザーに見せない(カスタムエラーページを使う)
  config.consider_all_requests_local = false

  # キャッシュを有効化(→ [第24章](https://qiita.com/harapeco-mgn/items/fc2ffbd0035b8f9f3a39))
  config.action_controller.perform_caching = true
  config.cache_store = :solid_cache_store

  # HTTPSを強制
  config.force_ssl = true

  # ログはinfoレベルのみ(debugは出さない)
  config.log_level = :info

  # プリコンパイル済みアセットを配信
  config.public_file_server.enabled = true
end

test.rb の特徴

# config/environments/test.rb
Rails.application.configure do
  # テスト専用DBを使う(database.yml の test: セクション)
  # → 本番・開発DBには絶対に触れない

  # テスト中はメールを実際に送らず、テストコードで内容を検証できる
  config.action_mailer.delivery_method = :test

  # 例外を raise するので、テストがクラッシュして失敗する
  config.consider_all_requests_local = true
  config.action_dispatch.show_exceptions = :rescuable
end

🚨 本番のエラーページをカスタマイズする(404 / 500)

production.rb で config.consider_all_requests_local = false にすると、エラー時に詳細なスタックトレースはユーザーに見せなくなります。代わりに表示されるのが エラーページ です。

デフォルトのエラーページ

Railsはデフォルトで public/ に静的なHTMLファイルを用意しています。

public/
├── 404.html    ← リソースが見つからない(RecordNotFound 等)
├── 422.html    ← CSRF検証失敗等
└── 500.html    ← サーバ内部エラー

これらは 静的HTMLファイル なので、アプリのレイアウト(ナビバーなど)は適用されません。デザインを統一したい場合は、Railsのルーティングで動的に返す設定にします。

Railsのルーティングでエラーページを返す

# config/application.rb
config.exceptions_app = self.routes
# config/routes.rb
match "/404", to: "errors#not_found",             via: :all
match "/422", to: "errors#unprocessable",         via: :all
match "/500", to: "errors#internal_server_error", via: :all
# app/controllers/errors_controller.rb
class ErrorsController < ApplicationController
  # 認証チェックを飛ばす(ログアウト中でもエラーページを表示する)
  skip_before_action :authenticate_user!, raise: false

  def not_found
    render status: :not_found
  end

  def unprocessable
    render status: :unprocessable_entity
  end

  def internal_server_error
    render status: :internal_server_error
  end
end
<%# app/views/errors/not_found.html.erb %>
<div class="text-center py-20">
  <h1 class="text-6xl font-bold text-gray-300 mb-4">404</h1>
  <p class="text-xl text-gray-600 mb-8">ページが見つかりません</p>
  <%= link_to "トップに戻る", root_path,
              class: "bg-blue-600 text-white px-6 py-2 rounded" %>
</div>

💡 config.exceptions_app = self.routes を設定しても、development環境では詳細エラー画面が優先されます。開発中に本番のエラーページを確認したい場合は、config/environments/development.rb で config.consider_all_requests_local = false に変更します。


🔑 Rails.env — コードの中で環境を判定する

Rails.env を使うと、実行中の環境をコードの中から判定できます。

# 環境を確認する
Rails.env            # => "development" / "test" / "production"
Rails.env.development?  # => true / false
Rails.env.test?         # => true / false
Rails.env.production?   # => true / false

使用例:初期データを開発環境でのみ投入する

# db/seeds.rb
if Rails.env.development?
  # 開発用ダミーデータ(Faker)— 本番では実行しない
  Faker::Config.locale = 'ja'  # 日本語名を生成するためにロケールを設定
  100.times do
    User.create!(
      name:  Faker::Name.name,           # => "佐藤 太郎"(ja ロケール時)
      email: Faker::Internet.unique.email
    )
  end
end

# 本番・開発共通の初期データ(管理者アカウント等)
User.find_or_create_by!(email: "admin@example.com") do |user|
  user.name     = "管理者"
  user.password = Rails.application.credentials.admin_password
end

使用例:本番環境でのみ外部サービスに送信する

# app/services/notification_service.rb
def notify(message)
  if Rails.env.production?
    # 本番でのみ Slack に通知を送る
    SlackNotifier.send(message)
  else
    # 開発・テストではログに出すだけ
    Rails.logger.info "[Notification] #{message}"
  end
end

💡 テストコードに Rails.env.production? を書かない
テストコード内で環境を判定する条件分岐を使うと、テストの信頼性が落ちます。代わりにスタブやモックを使います(→ 第22章)。


🔐 credentials と環境変数 — 秘密情報の管理

APIキーやDB接続情報など、コードに直書きしてはいけない情報を 秘密情報 と呼びます。Gitリポジトリに入れてしまうと、GitHubに公開したときに外部から見えてしまいます。

2つの管理方法

方法 仕組み 向いている場面
credentials 暗号化ファイル + 復号キーをセットで管理 チームでGit経由で秘密情報を共有したい
環境変数 サーバやCI/CDツールに直接設定する変数 Render/HerokuなどのPaaSを使う

credentials の使い方

# 暗号化ファイルを編集する(エディタが開く)
$ EDITOR=vi rails credentials:edit
# config/credentials.yml.enc(編集画面のイメージ)
aws:
  access_key_id:     AKIAIOSFODNN7EXAMPLE
  secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

jwt_secret_key: "my-super-secret-jwt-key-change-this"
resend_api_key: "re_xxxxxxxxxxxxxxxxxxxx"
admin_password: "initial-admin-password"
# コードからの読み出し
Rails.application.credentials.aws[:access_key_id]
Rails.application.credentials.jwt_secret_key
Rails.application.credentials.resend_api_key

credentialsのファイル構成:

ファイル Gitに含める 説明
config/credentials.yml.enc ✅ 含める 暗号化済みなので安全
config/master.key ❌ 含めない 復号キー。流出したら全て読まれる

master.key は .gitignore にデフォルトで記載されているので、意図的に追加しない限りGitに含まれません。チームで共有する場合は、Slack や 1Password などの安全な手段で渡します。

環境変数の使い方(RenderやHerokuの場合)

クラウドサービスを使う場合は、ダッシュボードで環境変数を設定するのが一般的です。

# Rails から環境変数を読む
ENV["DATABASE_URL"]
ENV["RAILS_MASTER_KEY"]
ENV["STRIPE_SECRET_KEY"]
# config/environments/production.rb での例
config.action_mailer.smtp_settings = {
  user_name: ENV["SMTP_USERNAME"],
  password:  ENV["SMTP_PASSWORD"],
  address:   ENV["SMTP_ADDRESS"]
}

どちらを使うか

credentials を使う → チーム開発でGit経由で秘密情報を共有したい場合
環境変数を使う    → Render/Herokuなどのダッシュボードで設定する場合

両方混在させると管理が大変になるので、プロジェクトで統一する。
本シリーズ(KnowledgeNote)では credentials を基本にしている。

🛠️ KnowledgeNoteでの具体例

環境ごとのメール設定

# config/environments/development.rb
# 開発中はブラウザでメール内容を確認(実際には送らない)
config.action_mailer.delivery_method = :letter_opener_web
config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
# config/environments/test.rb
# テスト中はメールを送らずキューに溜める(RSpecで内容を検証できる)
config.action_mailer.delivery_method = :test
# config/environments/production.rb
# 本番では実際にResend経由でメールを送る(→ [第29章](https://qiita.com/harapeco-mgn/items/420a7d80595504b0444d))
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address:              "smtp.resend.com",
  port:                 587,
  user_name:            "resend",
  password:             Rails.application.credentials.resend_api_key,
  authentication:       :plain,
  enable_starttls_auto: true
}
config.action_mailer.default_url_options = {
  host: Rails.application.credentials.app_host
}

環境ごとのActive Storage設定(→ 第30章)

# config/environments/development.rb
config.active_storage.service = :local   # ローカルのディスクに保存

# config/environments/production.rb
config.active_storage.service = :amazon  # S3に保存

💼 面接で聞かれたら?

Q:Railsの3つの環境(development / test / production)の違いを教えてください。

「developmentは手元で開発するための環境で、コードの変更を自動検知したりエラーの詳細を画面に表示します。testはRSpec等のテスト実行用で、テスト専用のDBを使い本番データには触れません。productionは実際のユーザーが使う環境で、キャッシュを有効にしてパフォーマンスを上げ、エラーの詳細は隠してカスタムページを表示します。config/environments/ ディレクトリの各ファイルで設定を分けています。」

深掘りされたら:

  • 「credentialsとは?」→ 秘密情報(APIキー等)を暗号化してGitで管理する仕組み。credentials.yml.enc を master.key で復号して読む。master.key はGitに含めない。
  • 「本番と開発で動作が違ったときの原因は?」→ config/environments/ の設定差異が多い。キャッシュの有無、アセットの読み方、ログレベル、メール設定の違いが原因になることがある。
  • 「テストが本番と同じ環境で動かないのはなぜ?」→ テスト環境は専用DBを使い、本番データには触れないよう意図的に分離されている。

🔗 もっと深く知りたい人へ(1次情報リンク)


まとめ

  • ✅ development / test / production の3環境がある。RAILS_ENV で切り替え、rails server はデフォルトでdevelopment
  • ✅ config/environments/ の各ファイルで環境ごとの設定を分離する
  • ✅ Rails.env.production? でコードの中から環境を判定できる
  • ✅ 秘密情報は credentials(暗号化ファイル)または環境変数で管理。master.key は絶対にGitに含めない
  • ✅ テスト環境は専用DBで動く。本番データには触れない
  • ✅ 本番の404/500ページは config.exceptions_app = self.routes でRailsのビューとして返せる

📚 シリーズ目次:「今さら学ぶ」シリーズ — はじめに

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?