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

【Day 39】VS Codeでコンテナ内C#開発・デバッグ・ブレークポイント実行 〜完全分離された環境をF5キーで直感デバッグ〜

Day 39 アイキャッチ
▲ Day 39: VS Codeでコンテナ内C#開発・デバッグ・ブレークポイント実行 〜完全分離された環境をF5キーで直感デバッグ〜
🐳

「Dockerコンテナの中だから、デバッグはログ出力で我慢する」なんて思っていませんか?

前回のDay 38では、.devcontainer/devcontainer.json を使って開発環境のすべてをコード化(IaC)し、Gitでチーム共有する手法を学びました。
しかし、現場のエンジニアから最もよく聞かれる不安がこれです。
「コンテナの中で動いているC#アプリって、本当にVisual Studioのようにブレークポイントで止めて、ステップ実行や変数の中身を見られるの?」
結論から申し上げます。ローカルPC直接実行と1ミリも変わらない快適さで、F5キーを押すだけで完全にデバッグできます!
ホストのVS Codeとコンテナ内のMicrosoft公式デバッガ(vsdbg)が阿吽の呼吸で連携するため、ブレークポイント設定、F10ステップオーバー、F11ステップイン、変数ウォッチ、さらには dotnet watch によるホットリロードまで自由自在です。本講義では、コンテナ内デバッグの裏側の仕組みから、launch.jsonの実践設定、バグ修正Git運用まで徹底解説します!

📋 本講義の学習ロードマップ
  • 第1章:30年選手の苦笑い:「リモートデバッグの苦行」とポート開放のトラウマ
  • 第2章:コンテナ内デバッグの裏側:VS Code Server と vsdbg の美しい連携アーキテクチャ
  • 第3章:徹底対比:従来の遠隔デバッグ vs Dev Containers(完全比較表)
  • 第4章:現場の2刀流:ホットリロード(dotnet watch)と F5 ステップ実行の使い分け戦略
  • 第5章:launch.json と tasks.json の完全解説:自動ビルドからデバッガ起動まで
  • 第6章:【実践ハンズオン】ASP.NET Core Web API をコンテナ内でF5デバッグ&変数ウォッチ
  • 第7章:コンテナ内統合ターミナルでの dotnet CLI 活用とログ監視テクニック
  • 第8章:Git連携:Git blame からバグ特定 ➔ コンテナ内即修正 ➔ テストコミットの黄金ループ
  • 第9章:本日の理解度セルフチェック&次回予告

1 30年選手の苦笑い:「リモートデバッグの苦行」とポート開放のトラウマ

長年Windowsやオンプレミスサーバーでシステム開発に携わってきたベテランエンジニアほど、「別のマシンや仮想環境で動くプログラムのデバッグ」と聞いただけで身構えてしまうのではないでしょうか。

かつてのリモートデバッグといえば、以下のような苦難の連続でした:

  • リモートサーバー側に「Visual Studio Remote Debugger(msvsmon.exe)」を手動で配置・起動しなければならない
  • ファイアウォールで特定ポート(4020〜4026など)を開放する申請を出し、インフラ担当者と調整する
  • ネットワーク認証やドメイン参加要件が厳しく、接続しようとしても「アクセスが拒否されました」で半日潰れる
  • 対象プロセスのプロセスID(PID)をタスクマネージャーで探し出して手動アタッチした瞬間、サーバー全体が重くなる
  • 手元のソースコードとサーバー上のDLLのビルドタイムスタンプが1秒でも異なると「シンボルが一致しません」と警告されてブレークポイントが白抜き無効化される

このようなトラウマから、「コンテナという隔離されたLinux環境の中で動いているC#アプリをデバッグするなんて、どうせ設定がややこしくて実用に耐えないはずだ。大人しく Console.WriteLine や ILogger でログを吐き出して目で追うしかない」と諦めてしまう現場が後を絶ちません。

しかし、その常識は Dev Containers の登場によって完全に過去のものとなりました!

2 コンテナ内デバッグの裏側:VS Code Server と vsdbg の美しい連携アーキテクチャ

なぜ Dev Containers では、手元のVS Codeからキーボードの「F5」を押すだけで、コンテナ内部のC#コードでブレークポイントがピタッと止まり、ステップ実行ができるのでしょうか?

その秘密は、「外からネットワーク越しにリモートデバッグしているのではなく、デバッガ自体がコンテナの中に常駐して同居している」という画期的なアーキテクチャにあります。

コンテナ内デバッグの連携構造
▲ 【図解①】ホストVS Code・VS Code Server・コンテナ内.NETデバッガ(vsdbg)がシームレスに対話する3ステップ連携構造

この連携は以下の3ステップで寸分の狂いもなく実行されます:

  1. ① ホスト側:VS Code UI
    ホストPC上のVS Codeは、エディタの画面描画、キー入力、ブレークポイントの赤丸表示、変数監視ウィンドウの描画など「UIフロントエンド」のみを担当します。
  2. ② 境界通信:VS Code Server
    コンテナ内部にはヘッドレスな「VS Code Server」が稼働しており、ホストのVS Codeと内部IPCパイプ(Docker exec / ソケット通信)で超高速に対話します。外部ポートを開放する必要は一切ありません。
  3. ③ コンテナ内:.NETデバッガ(vsdbg)
    Microsoftが提供するLinux用.NETデバッガエンジン「vsdbg」がコンテナ内部で直接起動します。vsdbgは同じコンテナ内で稼働するASP.NET Coreのプロセスを直接制御し、スレッドの停止・再開、メモリ上の変数読み取りを超高速に行います。

つまり、ホストのVS Codeから見れば「あたかもローカルで動いているプロセス」であり、コンテナ内のデバッガから見れば「同じローカルLinux内で動くプロセス」なのです。ネットワークの遅延やファイアウォール設定の苦しみは、構造上100%存在しません。

3 徹底対比:従来の遠隔デバッグ vs Dev Containers(完全比較表)

旧来のVM・リモートデバッグ運用と、現代のDev Containersによるデバッグ体験の違いを一覧表で整理してみましょう。

従来の遠隔デバッグ vs Dev Containers
▲ 【図解②】ポート開放と手動アタッチに苦しんだ従来のリモートデバッグと、F5キー一発で即時ブレーク可能なDev Containersの比較
比較項目 旧来:リモートデバッグ(VM/遠隔サーバー) 現代:Dev Containers(コンテナ内F5)
セットアップ手順 サーバーにツール配置、FWポート開放、管理者権限設定で数時間〜半日 ゼロ(VS Code拡張機能がvsdbgを全自動配置)
デバッグ開始操作 プロセス一覧からPIDを目視で探し「アタッチ」 F5キーを押すだけ(ビルド・起動・アタッチ全自動)
ポート開放・セキュリティ デバッグ用生ポートを外部へ晒すためセキュリティリスク大 外部ポート開放不要(Docker内部パイプ通信のみ)
ソースコード同期 手元とサーバーの差分でシンボル不一致エラーが多発 ホストのワークスペースをコンテナへマウント共有(完全一致)
操作レスポンス ネットワーク遅延でステップ実行や変数ホバーがカクつく 爆速・超快適(ローカル直接実行と寸分違わぬ反応速度)

4 現場の2刀流:ホットリロード(dotnet watch)と F5 ステップ実行の使い分け戦略

コンテナ内でC#開発を行う際、現場のハイパフォーマーが実践しているのが「ホットリロード」と「F5デバッグ」の賢い使い分け(2刀流)です。

ホットリロード vs F5ステップ実行
▲ 【図解③】コード保存で即時反映する「dotnet watch」と、1行ずつ精密に追跡する「F5ブレークポイント」の2刀流使い分け術

常にF5デバッグで動かしていると、わずかなコード修正でもビルドとプロセスの再起動が走り、数秒〜数十秒の待ち時間が発生します。開発のフェーズに合わせて最適なモードを選択しましょう。

⚡ dotnet watch(ホットリロード)

【利用シーン】
UIの見た目微調整、APIレスポンスの文言修正、バリデーションロジックの追加など、素早い試行錯誤を行いたい時。

【特徴】
コードを保存(Ctrl+S)した瞬間に、プロセスを再起動することなく実行中アセンブリに差分パッチが適用されます。ブラウザやSwaggerのリフレッシュだけで即座に結果を確認できます。

🔍 F5 デバッグ(ブレークポイント)

【利用シーン】
複雑な条件分岐の判定ミス、例外(Exception)の発生原因特定、データベースから取得した複雑なオブジェクト構造の精査など。

【特徴】
狙ったコード行で処理を確実に一時停止。ローカル変数、呼び出し履歴(コールスタック)、イミディエイトウィンドウによる式評価で、バグの根本原因をミリ単位で暴き出します。

5 launch.json と tasks.json の完全解説:自動ビルドからデバッガ起動まで

VS Codeで「F5」を押したときに、自動で最新コードを dotnet build し、生成されたDLLにデバッガをアタッチする設定は、.vscode/launch.json と .vscode/tasks.json のペアによって実現されます。

Dev Containers環境では、コンテナ内の絶対パス(例: /workspace/...)を意識する必要がありますが、${workspaceFolder} マクロを使えばOS差異を意識することなく完全ポータブルに定義できます。

① .vscode/tasks.json(事前ビルドタスクの定義)

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build",
      "command": "dotnet",
      "type": "process",
      "args": [
        "build",
        "${workspaceFolder}/MyWebApi.csproj",
        "/property:GenerateFullPaths=true",
        "/consoleloggerparameters:NoSummary"
      ],
      "problemMatcher": "$msCompile",
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}

② .vscode/launch.json(F5起動・デバッガ連携の定義)

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C#: Launch .NET Web API (Container)",
      "type": "dotnet",
      "request": "launch",
      "preLaunchTask": "build",
      "program": "${workspaceFolder}/bin/Debug/net8.0/MyWebApi.dll",
      "args": [],
      "cwd": "${workspaceFolder}",
      "stopAtEntry": false,
      "serverReadyAction": {
        "action": "openExternally",
        "pattern": "\bNow listening on:\s+(https?://\S+)",
        "uriFormat": "%s/swagger"
      },
      "env": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://+:5000"
      }
    }
  ]
}
💡 ここがプロのポイント!
preLaunchTask: "build" を指定することで、F5キーを押した瞬間に tasks.json の build タスクが先行して走り、最新コードがコンパイルされます。コンパイルエラーがあればデバッグ起動が自動で中断されるため、「古いアセンブリのままデバッグして混乱する」事故を100%防止できます。

6 【実践ハンズオン】ASP.NET Core Web API をコンテナ内でF5デバッグ&変数ウォッチ

それでは、実際にコンテナ内でASP.NET Core Web APIを起動し、ブレークポイントで止めて変数を検査するハンズオンを実施してみましょう!

ステップ1:検証用Minimal APIコード(Program.cs)

計算処理とオブジェクト生成を含むシンプルなエンドポイントを用意します。

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/api/order/calculate", (int quantity, decimal unitPrice) =>
{
    // ★ ここにブレークポイント(F9)を設定!
    var subtotal = quantity * unitPrice;
    var taxRate = 0.10m;
    var taxAmount = Math.Round(subtotal * taxRate, 2);
    var grandTotal = subtotal + taxAmount;

    var response = new
    {
        Quantity = quantity,
        UnitPrice = unitPrice,
        Subtotal = subtotal,
        TaxAmount = taxAmount,
        GrandTotal = grandTotal,
        ServerTime = DateTime.UtcNow
    };

    return Results.Ok(response);
});

app.Run();

ステップ2:ブレークポイント設定とF5実行

  1. var subtotal = quantity * unitPrice; の行の左端(行番号の左隣)をクリックして赤丸を点灯させます(または該当行で F9 キーを押下)。
  2. キーボードの F5 を押下します。自動的にビルドが走り、コンテナ内でAPIが起動します。
  3. ホストPCのブラウザまたはターミナルから以下のURLをリクエストします:
    curl "http://localhost:5000/api/order/calculate?quantity=5&unitPrice=1200"
  4. リクエストを送った瞬間、VS Codeのエディタが黄色くハイライトされ、該当行で処理がピタッと一時停止します!

ステップ3:変数ウォッチとステップ実行の操作方法

ショートカットキー 機能名 コンテナ内での動作
F10 ステップ オーバー 関数を丸ごと実行し、次の行へ進む
F11 ステップ イン 呼び出しているメソッドの内部へ潜り込んでデバッグする
Shift + F11 ステップ アウト 現在のメソッドを脱出して呼び出し元に戻る
F5 続行(Continue) 次のブレークポイントまで一気に処理を進める

左サイドバーの「変数(Variables)」パネルには、コンテナ内で動くC#の quantity (5) や unitPrice (1200) の値がリアルタイム表示されます。さらに変数の上にマウスカーソルをホバーするだけで値がポップアップします!

7 コンテナ内統合ターミナルでの dotnet CLI 活用とログ監視テクニック

VS CodeでDev Containersを開いているとき、Ctrl + ` で開く「統合ターミナル」は、ホストのPowerShellではなく「コンテナ内部のLinux bash/sh」に直接接続されています。

そのため、ホストPCに.NET SDKが一切インストールされていなくても、コンテナ内ターミナルで以下の強力なコマンド群が何でも実行できます:

# 1. コンテナ内でホットリロード開発を開始
dotnet watch run --urls "http://+:5000"

# 2. 単体テストを実行して合否判定
dotnet test --logger "console;verbosity=detailed"

# 3. NuGetパッケージの追加(コンテナ内で解決)
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

# 4. EF Coreマイグレーションの実行
dotnet ef database update

8 Git連携:Git blame からバグ特定 ➔ コンテナ内即修正 ➔ テストコミットの黄金ループ

Dev Containersの真価は、Gitと完璧に連動したトラブルシューティング運用にあります。

Git連携とバグ特定・修正ループ
▲ 【図解④】Git履歴から不具合箇所を特定し、同一コンテナ環境で再現・F5検証・テスト・修正コミットを爆速で回すチーム開発運用フロー

本番やステージングで不具合が報告された際、チーム開発では以下の3ステップでバグを撲滅します:

  • ① Git履歴・blameで変更履歴を特定
    VS CodeのGitLensや git blame を活用し、どのコミット・どのPRで入ったコードが怪しいかを特定。ブランチを切り替えて問題のコードをチェックアウトします。
  • ② コンテナ内でF5検証・再現・即修正
    環境の差異がゼロのコンテナ環境だからこそ、本番と同じ挙動がローカルで忠実に再現します。F5デバッグでブレークポイントを張り、変数の中身を確認しながらコードを安全に修正します。
  • ③ コンテナ内で全テスト実行・即コミット&PR
    コンテナ内ターミナルで dotnet test を流し、既存テストがすべてグリーン(合格)であることを検証。自信を持って修正コミットをプッシュし、Pull Requestを作成します。

🤖 AIエージェントへの指示プロンプト例(Antigravity / Claude Code / Copilot)

VS Codeの launch.json や tasks.json の記述に迷ったときは、AIエージェントに以下のように指示することで、最適な設定を即座に生成させることができます。

【指示プロンプト例】
VS CodeのDev Containers環境で稼働している.NET 8 Web APIプロジェクトに対して、
F5キーを押した際に自動ビルドを行い、コンテナ内のvsdbgでデバッグ起動するための
.vscode/launch.json と .vscode/tasks.json を生成してください。
ポートは5000番をリッスンし、Swagger UIへ自動連携する設定を含めてください。

9 本日の理解度セルフチェック&次回予告

🎯 本日の最重要セルフチェック

  1. コンテナ内デバッグにおいて、ホストVS Codeとデバッガ(vsdbg)はどのようなアーキテクチャで通信していますか?
    (回答目安:コンテナ内に常駐するVS Code ServerとホストUIが内部パイプラインで連携し、デバッガvsdbg自体がコンテナ内部で直接プロセスを制御しているため、外部ポート開放不要で遅延なくローカル同等に動作する点)
  2. 「dotnet watch」と「F5ブレークポイント実行」はどのように使い分けるのが最も効率的ですか?
    (回答目安:画面確認や軽微なコード修正はホットリロードで即時反映させ、複雑なロジック不具合や例外解析の際はF5で1行ずつ停止・変数精査を行う点)
  3. tasks.json の preLaunchTask を指定する最大のメリットは何ですか?
    (回答目安:F5押下時に事前ビルドを強制実行し、コンパイルエラーを検知して古いアセンブリでの誤デバッグを未然に防止できる点)
🚀 次回予告:Day 40「コンテナ内でのGit操作・SSH鍵・GPG署名のフォワーディング」

Dev Containerの中で開発が快適にできるようになったら、次に直面するのが「コンテナの中からGitHubへの git push や git commit 署名をどう安全に行うか?」という認証の壁です。
コンテナの中にSSH秘密鍵を直接コピーするのは重大なセキュリティリスク!
次回は、ホストPCのSSH AgentやGit設定をセキュアにコンテナ内へ共有する「SSH Agent Forwarding & 署名フォワーディング術」を徹底解説します!お楽しみに!

コメント

このブログの人気の投稿

【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版のオンラインプレーを楽しむ方法