環境差異をどこまで許容するか
開発をしていると「ローカルでは動いたのに本番で動かない」という問題に直面することがあります。原因の多くは環境差異です。
環境差異を小さくすることは望ましいですが、開発体験とのトレードオフが存在します。この記事では、C4モデルのデプロイメント図を使って環境差異を可視化するアプローチを紹介します。
環境差異は小さい方が良い
一般に、環境差異は小さい方が良いです。
例えば、Twelve-Factor Appの「10. Dev/Prod Parity」では、開発環境と本番環境の間にある3つのギャップを小さくすることを推奨しています。
Twelve-Factor App とは
Heroku の共同創業者 Adam Wiggins らが提唱した、モダンな SaaS アプリケーションを構築するための12の原則。コードベース管理、依存関係の明示、設定の環境変数化、ステートレスなプロセス、開発/本番環境の一致などを定めている。
- 時間のギャップ - 開発からデプロイまでに数週間〜数ヶ月かかる
- 人材のギャップ - 開発者がコードを書き、運用者がデプロイする
- ツールのギャップ - 開発では Nginx + SQLite、本番では Apache + MySQL を使う
この記事で扱う環境差異は ツールのギャップ です。
環境差異の影響
- 本番でしか再現しないバグ
- 「動くはず」という過信
- 継続的デプロイの阻害
環境差異による障害の例
環境差異が原因で発生しうる問題の例です(Twelve-Factor App より)。
| 本番環境 | ローカル開発環境 | 問題 |
|---|---|---|
| PostgreSQL | SQLite | SQL方言の違いでクエリが失敗 |
| Memcached | ローカルメモリ | キャッシュの挙動の違い |
開発体験とのトレードオフ
しかし、本番環境を忠実に再現しようとすると、ローカル開発環境が複雑になる傾向があります。
- 起動が遅くなる
- 設定が増える
- デバッグしづらくなる
開発サイクルが遅くなり、「面倒だからローカルでテストしない」という逃避につながりかねません。
C4モデルのコンテナ図とデプロイメント図
環境差異を可視化するために、C4モデルのコンテナ図とデプロイメント図を使います。C4モデルはソフトウェアアーキテクチャを階層的に表現する図法で、コンテキスト図・コンテナ図・コンポーネント図・コード図の4階層と、それをサポートするデプロイメント図などがあります。
ここでは、コンテナ図とデプロイメント図の2つを使います。
| 図 | 問い | 視点 |
|---|---|---|
| コンテナ図 | 何が動くか | 論理構成 |
| デプロイメント図 | どこで動くか | 物理配置 |
コンテナ図は「何が動くか」を定義する論理的な構成であり、環境によらず同一です。一方、デプロイメント図は「どこで動くか」を表現するため、環境ごとに異なりえます。このデプロイメント図の違いが環境差異です。
以下では、典型的なWeb3層のアプリケーションを例に、コンテナ図とデプロイメント図を作成します。
本番環境はAWSにデプロイし、フロントエンドをS3、バックエンドをLambda、データベースをRDS PostgreSQLで構成する想定です。
コンテナ図
このコンテナ図に対応するデプロイメント図を、本番環境とローカル開発環境それぞれで作成します。
デプロイメント図 - 本番環境
デプロイメント図 - ローカル開発環境
デプロイメント図をもとに、このアプリケーションの本番環境とローカル開発環境の差異を一覧化してみると、以下のようになります。
| コンテナ | 本番環境 | ローカル開発環境 | 差異 |
|---|---|---|---|
| CDN | CloudFront | なし | エッジキャッシュがない |
| Frontend | S3 | Docker コンテナ | ビルド成果物は同一 |
| Backend | Lambda | Docker コンテナ | ライフサイクル、コールドスタート、タイムアウト(後述) |
| Database | RDS PostgreSQL | PostgreSQL コンテナ | エンジン同一、マネージド差異のみ |
具体例:Lambda をローカルでどう扱うか
先ほどの表で Backend の差異が「ライフサイクル、コールドスタート、タイムアウト」となっていました。ローカル開発環境で Lambda をどう扱うかを例に、この差異の許容範囲を検討してみます。
構成例
Lambda をローカルで扱う方法には複数の選択肢があります。
Docker コンテナ
Lambda Web Adapter
SAM CLI
実AWS環境へデプロイ
選択肢の比較
本番との差異が小さいほど開発体験は悪化する傾向にあります。
| 方法 | 本番との差異の例 | 開発体験(主観) |
|---|---|---|
| Docker コンテナ | ライフサイクル、コールドスタート、タイムアウト | ◎ |
| Lambda Web Adapter | コールドスタート、タイムアウト | ○ |
| SAM CLI | コールドスタート | △ |
| 実AWS環境へデプロイ | なし | × |
他にも Serverless Offline、LocalStack などの選択肢もあります。
議論のポイント
例えば、以下のような観点で検討できます。
- ライフサイクルの差異を許容できるか?
- コールドスタート・タイムアウトの再現が必要か?
- 開発体験と本番環境の再現、どちらを優先するか?
まとめ
- 環境差異は小さい方がよい(Twelve-Factor App)
- しかし開発体験とのトレードオフがある
- デプロイメント図で差異を可視化し、チームで議論できる
差異を許容する場合も、意図的に許容していることを明示できます。図があれば、将来のチームメンバーも判断の経緯を理解できます。






