スキップしてメイン コンテンツに移動

【Day 25】複数環境設定の切り替え(docker-compose.override.yml) 〜ローカル開発とCI・本番の構成を安全に多重合成するベストプラクティスとC#環境分離設計〜

Day 25 アイキャッチ
▲ Day 25: 複数環境設定の切り替え(docker-compose.override.yml)
🔀
受講生の皆さん、お疲れ様です! Docker/コンテナ実践講座の専任講師です。
前回【Day 24】では、.env と .gitignore を駆使してパスワードや機密情報を安全に隔離し、Gitリポジトリをチーム共有するセキュリティ手法を学びました。
これで安全なマルチコンテナ環境が整いましたが、次のステップとして「環境ごとの構成の違い」という現場特有の壁に直面します!
「開発環境ではホストPCからSQL ServerやRedisに直接GUIツールで繋ぎたいからポートを公開したい」「でも本番やCI環境では余計なポートは絶対に塞ぎたい」「ソースコードのホットリロードはローカルだけに適用したい」…
環境ごとにYAMLファイルを丸ごとコピーして別名保存していませんか?
本日【Day 25】は、Docker Compose最強の拡張機能である「docker-compose.override.yml による構成の自動多重合成」と、「C#(ASPNETCORE_ENVIRONMENT)と連動した環境切り替え設計」を完全攻略します!

① 導入・本日の達成目標

Docker ComposeでWeb APIとDBを定義した docker-compose.yml を運用していると、必ず以下のようなジレンマが生まれます。

⚠️ 現場で陥りがちなアンチパターン(構成ファイルの丸ごとコピー増殖):
開発用の設定と本番用の設定を分けたいあまり、docker-compose.dev.yml と docker-compose.prod.yml をそれぞれフルセットで作成してしまう。
その結果、共通のDBサービス定義や環境変数に変更が入るたびに「両方のファイルを修正・同期」しなければならず、修正漏れによる本番障害が多発する…!

従来のオンプレミス運用でも、web.config や設定ファイルを「開発サーバー用」「ステージング用」「本番用」と手動でコピー&書き換えし、デプロイ時に事故を起こしていた歴史がありました。
Docker Composeはこの問題を極めてスマートに解決する「override(上書き・合成)機構」を標準で備えています。

🎯 本日の到達目標(ゴール宣言)

  • Composeの自動多重合成(override)の仕組み: docker-compose.override.yml がデフォルトで自動読み込みされ、基本設定とマージされる挙動を理解する。
  • 開発環境 vs 本番・CI環境の差分設計: 共通設定(ベース)と、環境固有の差分(ポート・マウント・環境変数)を最小限のコードで分離する。
  • -f オプションによる明示的合成: 本番環境やCIパイプラインで特定のYAMLファイル同士を合成して起動するコマンド手順をマスターする。
  • C#(ASP.NET Core)の環境切り替え連動: ASPNETCORE_ENVIRONMENT の値をComposeから注入し、appsettings.Development.json と appsettings.Production.json を安全に切り替える実装を習得する。

② Compose設定の自動多重合成(override)メカニズム

まずは、Docker Composeが提供する「override機構」の基本ルールと、2つのファイルがどのように合体するのかを図解で確認しましょう。

Compose設定の自動合成(override)の仕組み
▲ 【図解①】Compose設定の自動合成(override)の仕組み(基本設定 + 上書き設定 = 最終適用設定)

暗黙のデフォルト:引数なしで2つのファイルが自動マージ

Docker ComposeのCLI(docker compose up)を実行した際、Composeはカレントディレクトリから以下の2つのファイルを自動的に順番に読み込み、メモリ上で合成(マージ)します。

  1. docker-compose.yml(第1読み込み): すべての環境で共有される基本設計図(サービス定義、コンテナ名、内部ネットワーク構成など)。
  2. docker-compose.override.yml(第2読み込み): 第1の基本設計図に対して、開発者のローカル都合で上書きしたい項目だけを追記した差分ファイル。

つまり、コマンド実行時に何もオプションを指定しなくても、自動的に 基本設定 + override設定 = 合成設定 が完成してコンテナが起動します!

💡 マージ(合体)の基本ルール:値の上書き vs リストの追加

  • スカラー値・辞書(キーと値のペア): image: や environment: の同じキーは、後から読み込まれた override ファイル側の値で上書きされます。
  • リスト(配列形式の項目): ports: や volumes: などの配列は、両方のファイルの内容が追加(結合)されます。

③ ローカル開発用 vs 本番・CI用の構成差異と設計パターン

なぜこの合成機構がこれほど重宝されるのでしょうか?
それは、「ローカル開発環境」と「本番・ステージング環境」で求められる要件が真逆であるためです。

開発環境 vs 本番環境の構成差異
▲ 【図解②】ローカル開発環境 vs 本番・CI環境の構成差異(ホットリロード重視 vs 堅牢・軽量重視)

開発環境と本番環境の要件差異を整理したのが下表です。

設定項目 ローカル開発環境(override.yml) 本番・CI環境(prod.yml)
ポート公開(ports) 5000:80, 1433:1433(直接アクセス用) 非公開(リバースプロキシや内部NW経由)
ソースコードマウント バインドマウント(ホットリロード有効) マウントなし(ビルド済みイメージのみ)
ビルド方式 build: .(ローカル最新コードからビルド) image: myregistry.io/myapp:1.2.0(検証済み固定)
ASPNETCORE_ENVIRONMENT Development(Swagger有効・詳細エラー) Production(セキュアエラー・最適化)

実例:最小限の差分で記述する美しいYAML構成

それでは、実際のYAMLコードで設計例を見てみましょう。
まず、全環境共通のベース定義 docker-compose.yml です。

# docker-compose.yml(Git共有する共通ベース設計図)
services: webapi: build: context: . dockerfile: Dockerfile environment: - DOTNET_RUNNING_IN_CONTAINER=true networks: - backend-network depends_on: - sqlserver sqlserver: image: mcr.microsoft.com/mssql/server:2022-latest environment: - ACCEPT_EULA=Y - MSSQL_SA_PASSWORD=${SA_PASSWORD} networks: - backend-network networks: backend-network: driver: bridge

ご覧の通り、docker-compose.yml には ports: や環境ごとの設定は一切書かれていません!
続いて、開発用の上書きファイル docker-compose.override.yml です。

# docker-compose.override.yml(ローカル開発者向けの差分ファイル)
services: webapi: ports: - "5000:8080" # ホストPCからSwaggerやAPIを直接叩くためのポート開放 environment: - ASPNETCORE_ENVIRONMENT=Development volumes: - ./src:/app/src # ソースコード変更の即時反映用(ホットリロード) sqlserver: ports: - "1433:1433" # SSMSやVS Codeのmsoql拡張から直接テーブルを見るための開放

開発者はカレントディレクトリで docker compose up と叩くだけで、この2つのファイルが自動結合され、開発に最も快適なポート開放&開発環境モードが起動します。

④ CLIコマンド完全制覇:-f オプションと config 検証

「ローカル開発では自動マージされるのは分かったけれど、本番環境やCI/CDパイプラインではどうやって別ファイルを適用するの?」
ここで使うのが、Compose CLIの -f(--file)フラグです!

-f オプションによる複数ファイル指定の3ステップ
▲ 【図解③】-f オプションによる複数ファイル指定と検証の3ステップフロー(暗黙合成・明示指定・config確認)

-f オプションを指定した瞬間の重要ルール

⚠️ 絶対に覚えておくべきComposeの挙動ルール:
docker compose に一度でも -f オプションを指定すると、「docker-compose.override.yml の暗黙の自動読み込みが無効化」されます!
したがって、本番用ファイル(例: docker-compose.prod.yml)を適用したい場合は、基本設定と本番用設定の両方を -f で明示的に渡します。
# 1. ローカル開発環境の起動(暗黙的に compose.yml + override.yml が合成される)
$ docker compose up -d

# 2. 本番・ステージング環境の起動(ベースとprod用を明示的に合成して起動)
$ docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# 3. 超便利!実際に合成された最終YAML設定の確認(ドライラン)
$ docker compose config

特に docker compose config は実務で必須の神コマンドです。
複数ファイルの合成結果がターミナル上にプレーンなYAMLとして一括出力されるため、「ポートが正しく上書きされているか」「環境変数が正しく注入されているか」をコンテナ起動前に100%確実に目視確認できます!

⑤ C# ASP.NET Core の環境変数切り替え(ASPNETCORE_ENVIRONMENT)実践

最後に、C#(.NET 8/9)エンジニアの現場視点で最も重要な「コンテナ内アプリの環境連動」を実装しましょう。

C# ASP.NET Core の環境変数切り替え
▲ 【図解④】C#(ASP.NET Core)の環境切り替えフロー(ComposeからASPNETCORE_ENVIRONMENTを注入する3ステップ)

ASP.NET Core は、起動時に ASPNETCORE_ENVIRONMENT という環境変数を参照し、自身の実行モードを決定します。
Composeの environment: でこの値を注入することで、C#のコードを1行も書き換えることなく挙動を自動分岐させることができます。

// Program.cs(ASP.NET Core 8.0 / 9.0)
var builder = WebApplication.CreateBuilder(args); // 1. コントローラーとSwaggerサービスの登録 builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // 2. 環境変数(ASPNETCORE_ENVIRONMENT)に基づく自動分岐 if (app.Environment.IsDevelopment()) { // ローカル開発時のみSwagger UIを有効化&詳細エラー表示 app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API Dev v1"); }); app.UseDeveloperExceptionPage(); } else { // 本番・ステージング環境では安全な汎用エラーハンドラーとHSTSを強制 app.UseExceptionHandler("/error"); app.UseHsts(); } app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.Run();

✨ appsettings.*.json の自動マージチェーン

ASPNETCORE_ENVIRONMENT=Development が注入された場合、.NETランタイムはまず appsettings.json を読み込み、その直後に appsettings.Development.json の値で上書き合成します。
さらに前回学んだ Composeの環境変数(ConnectionStrings__*)が最優先で重ね合わされるため、「共通設定 ➡ 環境別JSON ➡ コンテナ環境変数」の美しい3層カスケード構造が完成します!

⑥ 本日のまとめと理解度チェック

💡 本日の重要ポイント総まとめ

  • 設定の共通化とoverrideの役割: 全環境で共通のインフラ基盤は docker-compose.yml に集約し、開発固有のポートやマウントは docker-compose.override.yml に切り出す。
  • 暗黙の自動マージと -f による制御: 引数なしの docker compose up は override.yml を自動適用する。本番・CIでは -f compose.yml -f compose.prod.yml で明示指定する。
  • docker compose config の活用: 複数ファイルがどう合成されたかをコンテナ起動前にコマンド一発で可視化・点検する。
  • C#(ASPNETCORE_ENVIRONMENT)の連携: Composeから注入された環境名に応じて、Swaggerの有効化や appsettings.Development.json が自動反映され、安全な環境分離が実現する。
次回【Day 26】予告:
『docker compose up / down / build の実務コマンド完全マスター』〜バックグラウンド起動(-d)、差分再ビルド(--build)、コンテナ・ボリューム破棄(down -v)の実務頻出ワークフロー〜

コメント

このブログの人気の投稿

【Perfume】Perfume 3rd Tour 「JPN」さいたまスーパーアリーナに行って参りました~

Perfume 3rd Tour 「JPN」1月28日、29日の2daysで参戦して参りました。 ファンクラブ会員の選考抽選会に28日、29日の両日で申し込んでいたんですが、両方とも当選していたという嬉しい誤算。 仕事だぁ、なんだかんだと紆余曲折ありまして28日の参戦は危ぶまれていたのですが、なんとかかんとか28日は40分遅刻しながらも参戦、29日はフル参戦する事が出来ました(∩´∀`)∩

Perfume、2025年末で“コールドスリープ(活動休止)”へ──東京ドーム2daysの記録と、公式・各界・ファンの声

  1) 公式発表・基本情報 活動休止(コールドスリープ)を正式発表 2025年9月21日、公式サイト「 Perfumeより 」で、2026年から一度コールドスリープに入ると発表。再始動の意思(“新しいPerfume”として戻る)も明記。 Perfume Official Site 今後の運用告知(配信・上映など) 同21日付の「 今後のPerfumeに関して 」で、9/23(火・祝)東京ドーム公演の LIVESHIP全世界生配信 および 全国ディレイビューイング 決定を案内。特設サイトも併記。 Perfume Official Site +1 公式グッズ **「Perfume Calendar 2026」**発売決定(B2壁掛け/表紙+2カ月1枚×6枚+ポスター)。テーマは“フルーツ”。 Perfume Official Site 2) 東京ドーム2days(9/22・23)要点 公演タイトル: ZO/Z5 Anniversary “ネビュラロマンス” Episode TOKYO DOME 。日程・開場/開演・会場・物販等の実務情報は特設で公開。 Perfume Official Site 9/23公演を世界配信(LIVESHIP) /ディレイビューイング実施。 Perfume Official Site 海外向け報道(英語)も「 indefinite hiatus 」として広く配信。 The Times of India 国内英字メディアも速報。 朝日新聞 3) 現地レポ( メリ爺 )から見える空気 あなたの現地記録(9/24公開)を、ファクトと現場情景の両面で反映: 両日参戦 。22日は アリーナ 、23日は 1階席から俯瞰 。前日の発表を受け、開演前のザワつき→MC後に“いつもの一体感”へ。開演は22日 18:45 頃。オープニングは**P³ツアー東京ドーム(2020/2)**と同趣向で“回収”の演出。 メリ爺のゲーム万歳 MC所感 :解散ではなく前向きな休止で不安を和らげる内容。 かしゆか の涙、 のっち の気丈さ、 あ〜ちゃん の思い出語り──3人の結束と「 また戻る 」約束が強く刻まれた。 メリ爺のゲーム万歳 体感時間 : “3時間弱”級のボリューム ながら“過去一...

ニンテンドースイッチでオンラインゲームを遊ぶには?

モンスターハンターライズが発売になって、家族でモンハン楽しみたい人が増えたみたいですね。 某ブログの検索キーワードを調べると、モンハンを家族でやるにはどうしたらいいのか?を調べている人が沢山いるのがわかります。 ※これでも一部  家族で協力するにはSwitch2台、ソフトも2つ購入する必要があります。 1台のスイッチでは遊べませんし、ソフト1つでも遊べません。 でも、1台のスイッチで別々アカウントがあれば交代で遊ぶこともできますよ。セーブデータもしっかり分かれます。 Switchのオンラインゲームを家族で遊ぶ方法については以下の記事にまとめてますのでよろしければ参考にしてみてくださいね。 家族でモンスターハンターライズDL版のオンラインプレーを楽しむ方法