Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

productionやdevelopment、stagingという言葉の使い分けについて

morimorihogeです。関東圏は雨が多い気がしますね。さむい。

さて、今年も12月ということでアドベントカレンダーの季節がやってきました。
TechRachoアドベントカレンダーでは例年弊社(BPS株式会社)で普段記事をあまり書く機会がないメンバーにも広く記事を書く機会を作ろうという企画で、エンジニアメンバーに関わらず総務や採用メンバーにも何か書いてもらうという試みをしています。
なんとなく弊社メンバーの雰囲気に触れていただければと思います。

過去のアドベントカレンダー記事は以下からどうぞ

初回は僕から、11月の銀座Railsで発表した内容を記事に再構成してみました。

Webアプリ開発初心者を惑わすproduction / development / stagingというコトバ

プログラミングに限らず専門技術界隈は色々な「その業界でしか通用しない専門用語」があります。今回取り上げるproductiondevelopmentstagingという用語もその中の一つで、主にWebアプリケーション開発や業務システムなど、サーバーがいて通信するようなシステムの世界で使われる用語になります。
なお、日本語だとそれぞれ

  • production: 本番
  • development: 開発
  • staging: 検証

と対応することが多いかなと思います(異論は認める)。
こうした用語群は、例えば弊社でも得意なRailsアプリケーション開発を前提としたならば、

  • アプリケーションの動作モードを示すもの:RailsならRAILS_ENVに相当
  • システムが動作するサーバー環境を示すもの:本番サーバー、開発サーバーなど
  • GitやSubversion、ソースコードの特定バージョンを示すもの:Gitのタグ、ブランチなど

などにこれらの用語が出てくることがあります。まずはそれぞれ簡単に解説します。

アプリケーションの動作モード

昨今のアプリケーションでは、実行時に「動作モード」を指定できることが多いです。
例えば、RailsであればRAILS_ENVという環境変数を渡すことで、デフォルトでproductiondevelopmenttestという動作モードを切り替えることができます。
# プロジェクトによっては更に別途stagingといった環境を増やしているものを見ることもあります。

ここで指定する動作モードとは、主に当該アプリケーションを実行する時単体で見たときの振る舞いを切り替えるものを指します。
例えば、Railsであればそれぞれの動作モードには以下のような特徴があります。

  • productionモード
    • 本番モードで、動作中にソースコードが編集されない前提が取れるため、クラスキャッシュなどをアグレッシブに保持して効率化ができる(config.cache_classesやconfig.eager_load)
    • 静的ファイル配信はRailsサーバーからではなくnginxなどの手前Webサーバーから配信させる前提の設定(config.public_file_server.enabled = false)がされている
  • developmentモード
    • 起動中にソースコードが編集されてもRailsサーバーの再起動不要で変更結果が反映される(config.file_watcherconfig.cache_classesの無効化など)
    • 開発者のローカル環境ではいちいちnginxなどを立ち上げなくても良いように、public以下の静的ファイルもRailsサーバーが配信する(config.public_file_server.enabled = true
  • testモード
    • developmentモードに近いが、さらにCIやターミナル前提の設定などが付く(consider_all_requests_local = :stderr

なお、RAILS_ENVの場合は基本的に日本語で「本番モード」「開発モード」などと呼称することは少ないように思います(少なくとも僕の周辺では見かけたことがないです)。
また、「prodモード」や「devモード」といった呼称も見ませんので、この辺りは見分けるのに使えるかなと思います。

サーバー環境の種別

いわゆる「本番サーバー」「検証サーバー」「開発用サーバー」といった種別になります。
イマドキ運用中システムの動作環境が本番環境しかないということは流石にありえないとは思いますが、複数環境がある場合でもいくつの環境があるか、それぞれどの様な呼称をされているかなどはプロジェクトによってかなり異なります。

例えば代表的な分類だと、以下の様な3環境が挙げられるのではないかと思います。

  • 本番(production)環境
    • サービスインしているエンドユーザーが利用する環境。git-flowならmasterブランチが対応
  • 検証(staging)環境
    • 本番リリース前の動作検証を行う場所。git-flowならdevelopブランチが対応
    • ほとんど本番に近い環境だが、サーバースペックは落としてあったり、外部API接続がテスト環境に繋がっていたりなどが異なる
  • 開発(development)環境
    • 開発中の機能を見てもらう時などに使う場所。git-flowならfeatureブランチが対応
    • stagingより更にカジュアルな環境で、簡単に作って潰すような使われ方をするためにリソースはケチって立てることが多い

ちなみに、Rails開発に慣れている人にわかりやすく伝えるのであればCapistranoのStage名がこの種別に該当します。
# イマドキk8s使ってるからcapなんて使ってねーよという人はすみません

上記3つの代表的なもの以外にも、並行開発されているプロジェクトなら各チームや開発者ごとに開発環境を持っていたり、リリース確認がQA(Quality Assurance)チームのチェックの2段階になっていたりなど、この辺りはリリースフローや開発体制によってもかなり色々な組み合わせが存在します。

そういう意味では「一つの正解」がある部分ではなく、プロジェクト規模やリソース状況に応じて一番個性が出る部分だと言えます。

ソースコードの特定バージョン

GitやSubversionでブランチやタグを使ったリリース管理をする際に使われるものになります。
例えば、僕の好きなgit-flowなんかではmasterブランチが本番環境、developブランチが開発環境といった対応になっており、前述のサーバー環境と対応させるような運用が想定されています。

ここで、前述のようにサーバー環境が複数出てくると、より細かなリリースタグを打ちたいといったニーズが出てきます。
ありがちなのはdeployフローの中にrelease/prod_201912010900といった日時付きのタグを打つことで、何月何日何時の時点でどのコードがリリースされたのかを記録するといった用途になります。
※git-flowデフォルトのmaster / developブランチでは、どんどんmaster / developのHEADが進んでいってしまうので、タグを打たないと過去いつどのバージョンがリリースされていたのかを追うことができない

バグ報告などに対応する際、どの時点のバージョンで発生していたのかがはっきりわからないと調査が大変になってしまうため、こういったタグ管理が行われているプロジェクトはそこそこ多いのではないかと思います。

こんな時にこんがらがる!

さて、ここまででproduction / development / stagingにはそれぞれの意味があることを示してきましたが、これらが混同されると開発者内で混乱が生じることがあるかもしれません。

こんなシチュエーションを考えてみます。

  • AさんはBさんのPRをレビュー中、RAILS_ENV=productionのケースでエラーが発生してしまう可能性のあるコードを見かけたので「B君のコード、productionでエラーが出てるよ~」と指摘
  • Bさんはproductionでエラーが出てるという言葉を「本番(production)サーバーでエラーが出ている」と勘違いし、慌てて本番のエラーログや障害調査を始めてしまう

これは不幸なすれ違いのケースですね。Bさんの正気度が下がりそうなケースです。

他にも

  • AさんはCさんに「production(サーバー)用のAPIキーがきたので、サーバー環境のconfigに設定してほしい」と依頼
    • ※本来ならcapistranoで言うshared_filesなどのサーバー依存置き場への設定を意図
  • Cさんは「RAILS_ENV=productionの設定に反映すれば良い」と勘違いしてconfig/settings/production.ymlにAPIキーを配置してgit pushしてしまう(大惨事)

みたいなケースはどうでしょうか?ある程度経験のある開発者メンバーであればやらないミスだとは思いますが、CさんがRails開発はあまり詳しくないエンジニアなどの場合、Railsの流儀などには詳しくないので言われたとおりに作業をしてしまう、という可能性はなきにしもあらずではないでしょうか。

後は、

  • Aさんは新規で開発に参加してきたDさんに「Dさんのコード、レビューOKだからproduction(タグを付けてGitHub)に上げておいて」と依頼
  • Dさんは本番(production)サーバーにSSHで入っておもむろにgit pullとかし始める

なども、開発やdeployルールの前提条件がきちんとドキュメント化されていないと発生しないとも限らないです。

勘違いしない・させないためにどうするのか?

実際にはある程度以上経験のあるエンジニアであれば、この手のミスは実際に手を動かす前の時点ですれ違いに気づき、認識合わせをすることで回避できると思いますが、もし仮に間違って作業してしまった場合のことを考えると悲惨な結末になるケースもあるため、コミュニケーションにおけるストレスの原因になってしまう所です。

そのため、僕がSlackや各種コミュニケーションを行うときには以下の様な点を気にしていたりします。

  • アプリケーション動作モードを指す時には明示的にRAILS_ENVであることを示したり、productionモードdevelopmentモードの用にモードという呼称を使う
  • サーバー環境にはproductionではなくproddevelopmentではなくdevなどRAILS_ENVと完全一致しない名前を付けたり、prod環境dev環境という環境という呼称を使う
  • ソースバージョンタグには production ではなくrelease/productionなどの完全名やproductionタグなどの呼称を用いる

やっている事自体はちょっと気を使っているだけなのですが、こうしたちょっとした修飾子を付けるだけで認識齟齬の可能性が一気に減らせ、お互いにストレスのない開発ライフを送ることができます。

まとめ

個人的に年に1~2回くらいは「危なっかしいな~」と思うことを記事にしてみました。

この手の「用語を正確に使うように心がけ、複数の意味を持つ用語は特に注意する」というのは初心者はないがしろにしがちですが、熟練者ほど無意識のうちに大事にやっている部分ではないかと思います。
チーム開発では自分自身がわかっているだけではダメで、チーム内のメンバーとも認識齟齬がないようにしていかないといけないので、こうした気の遣い方ができる人はありがたいと個人的には感じます。

似たようなことは他の用語でもあると思いますが、こういった認識齟齬が出た際には相手の忖度力を非難するのではなく自分の説明力が足りないことを疑うと良いでしょう。
多くの場合、多少説明を丁寧にすることによって避けられる手間は地雷を踏んで火消しする手間に比べれば大したことないですしね。
※そもそもこの手の齟齬自体気にしなくて良い用に開発フローを自動化する、というのもありだと思います。

ではでは、また12月中にもう1~2本くらいはアドベントカレンダー記事を書こうと思います。よろしくおねがいします。

おたより発掘


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。