<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9031334347464664289</id><updated>2026-10-30T18:07:04.024+09:00</updated><category term="Perfume"/><category term="prfm"/><category term="日記"/><title type='text'>仮想空間の日常</title><subtitle type='html'>モニター越しに現実を体験する</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>70</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-4239404671301531311</id><published>2026-10-30T18:07:04.023+09:00</published><updated>2026-10-30T18:07:04.023+09:00</updated><title type='text'>【Day 32】git switch - やエイリアス設定で日常操作を10倍爆速化する</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1Zs0GuXoQWCHCl7iuyIFL7nEtpn1kMf39&quot; alt=&quot;Day 32 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 32】git switch - やエイリアス設定で日常操作を10倍爆速化する&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 31では、過去に一度解いたコンフリクトをGitが自動学習して再利用する魔法の機能&lt;strong&gt;「git rerere」&lt;/strong&gt;を学びました。&lt;br/&gt;
            そして本日のDay 32からは、日々のGit操作のタイピング量やマウス操作の手間を極限まで削ぎ落とし、開発スピードを何倍にも引き上げる&lt;strong&gt;「作業効率化テクニック」&lt;/strong&gt;へ突入します！&lt;br/&gt;
            テーマは、&lt;strong&gt;【git switch - やエイリアス設定で日常操作を10倍爆速化する】&lt;/strong&gt;です！&lt;br/&gt;
            「ブランチを切り替えるたびに、長くて複雑なブランチ名を手打ちしてタイポする…」&lt;br/&gt;
            「1日に何十回も &lt;code&gt;git status&lt;/code&gt; や &lt;code&gt;git branch&lt;/code&gt; をフルスペルで入力している…」&lt;br/&gt;
            「いま自分がどのブランチで作業していて、何件の未コミット変更があるのか、コマンドを打たないと分からない…」&lt;br/&gt;
            そんな日々の小さなタイムロスやストレスは、年間で数十時間もの無駄を生み出しています。&lt;br/&gt;
            直前ブランチへの1秒復帰（&lt;code&gt;switch -&lt;/code&gt;）、わずか2〜3文字で完結するプロ厳選のエイリアス（短縮コマンド）、そしてWindows/C#開発者の標準環境であるPowerShellプロンプトのGit情報可視化をマスターして、思考のスピードでコードを紡ぐ圧倒的開発フローを手に入れましょう！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        Gitのコマンドは非常に高機能ですが、日常的によく使うコマンドを毎回フルスペルで律儀に入力していると、キータイピングの負荷や誤入力によるストレスが蓄積します。&lt;br/&gt;
        特にVisual StudioやVS Codeを操作しながらターミナルでGitを叩くC#開発者にとって、キーボードとマウスの行き来や、長いブランチ名の入力は集中力を削ぐ最大の敵です。&lt;br/&gt;
        本講義では、Gitの標準機能である &lt;code&gt;git switch -&lt;/code&gt; やエイリアス登録、さらにPowerShellとの連携により、日常操作を劇的に高速化する実践ノウハウを体系的に解説します。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;code&gt;git switch -&lt;/code&gt; による直前ブランチへの「瞬間移動（ワンタッチ復帰）」を体得する&lt;/li&gt;
            &lt;li&gt;マウス操作や長文タイピングによる非効率を排除し、CLIを高速化する意義を理解する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git config --global alias.*&lt;/code&gt; を使ったプロ厳選の短縮エイリアス（st, sw, br, cm, lg等）を登録・活用する&lt;/li&gt;
            &lt;li&gt;Windows PowerShell環境で &lt;code&gt;posh-git&lt;/code&gt; や &lt;code&gt;Oh My Posh&lt;/code&gt; を導入し、ブランチ状態を常時プロンプトへ可視化する&lt;/li&gt;
            &lt;li&gt;C#プロジェクト（Visual Studio / VS Code）での日々のコーディング速度と開発快適性を大幅に向上させる&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: マウス操作や長文コマンドの遅さ vs 2文字エイリアスの超速世界 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】マウス操作や長文コマンドの遅さ vs 2文字エイリアスの超速世界&lt;/h2&gt;
    &lt;p&gt;
        まずは、GUIやフルコマンド入力と、最適化されたCLIエイリアス操作の生産性の違いを図解で確認しましょう。
    &lt;/p&gt;

    &lt;!-- 図解① --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1cOQDmMQ2nF4PivXonEF1RzfeAaSOP9Jq&quot; alt=&quot;マウス操作や長文コマンドの遅さ vs 2文字エイリアスの超速世界&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】マウス操作や長文コマンドの遅さ vs 2文字エイリアスの超速世界&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        SVNや従来のGUI運用では、マウスでメニューを探してクリックする動作に数秒のタイムロスが発生し、キーボードから手が離れることで思考のリズムが中断されていました。&lt;br/&gt;
        また、Git CLIを使う場合でも、&lt;code&gt;git status&lt;/code&gt; や &lt;code&gt;git checkout feature/user-auth-service-2026&lt;/code&gt; のように長文を毎回律儀に打ち込んでいると、タイポ（誤字）によるエラーが頻発します。&lt;br/&gt;
        エイリアスを設定すれば、わずか2〜3文字のキータッチで瞬時に目的の操作が完了し、思考のスピードを止めずに開発を継続できます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15.5px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #f1f5f9; border-bottom: 2px solid #cbd5e1;&quot;&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 25%;&quot;&gt;操作スタイル&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 35%; color: #991b1b;&quot;&gt;課題・タイムロス要因&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 40%; color: #1e40af;&quot;&gt;最適化後の効果&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;GUI / マウス操作&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;キーボードから手を離し、ダイアログを探してクリック（2〜5秒ロス）。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;キーボードホームポジションを維持したまま0.5秒で完結。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;長文フルコマンド&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;&lt;code&gt;git checkout&lt;/code&gt; や長いブランチ名の手打ちでタイポ・手首の疲労。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;&lt;code&gt;git sw -&lt;/code&gt; や短縮エイリアスで打鍵数を80%以上削減。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;状態確認の頻度&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;状態を知るために毎回 &lt;code&gt;git status&lt;/code&gt; を実行して画面が流れる。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;PowerShellプロンプトに常時表示され、確認コマンドすら不要に。&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- セクション③: git switch - による直前ブランチへの「瞬間移動」 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】git switch - による直前ブランチへの「瞬間移動」&lt;/h2&gt;
    &lt;p&gt;
        開発中によくあるシチュエーションが、「作業中のフィーチャーブランチから、最新の動作確認のために一時的に &lt;code&gt;main&lt;/code&gt; ブランチへ切り替え、用が済んだらすぐ元のブランチに戻りたい」というケースです。&lt;br/&gt;
        この時、元のブランチ名（例: &lt;code&gt;feature/issue-1042-payment-gateway-refactor&lt;/code&gt;）を再度打ち込んだり、履歴をスクロールしてコピペするのは非常に面倒です。&lt;br/&gt;
        ここで絶大な効果を発揮するのが、ハイフン（&lt;code&gt;-&lt;/code&gt;）を指定した &lt;strong&gt;git switch -&lt;/strong&gt; です！
    &lt;/p&gt;

    &lt;!-- 図解② --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1YOr29K8vnhnHPmN9TWkxE36pH54Eb6RV&quot; alt=&quot;git switch - による直前ブランチへの瞬間移動&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】git switch - による直前ブランチへの「瞬間移動」&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        &lt;code&gt;git switch -&lt;/code&gt; は、テレビのリモコンにある&lt;strong&gt;「前チャンネル」ボタン&lt;/strong&gt;と全く同じ働きをします。&lt;br/&gt;
        Gitは直前に滞在していたブランチ（またはコミット）の参照を内部的に保持しており、&lt;code&gt;-&lt;/code&gt; を渡すだけで、ブランチ名を一切指定することなく「1つ前に居たブランチ」へ瞬時にワープさせてくれます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; margin: 20px 0; font-family: Consolas, &#39;Courier New&#39;, monospace; font-size: 15px;&quot;&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 1. 長い名前の作業ブランチにいる状態&lt;/span&gt;&lt;br/&gt;
        $ &lt;span style=&quot;color: #38bdf8;&quot;&gt;git switch&lt;/span&gt; feature/issue-1042-payment-gateway-refactor&lt;br/&gt;
        Switched to branch &#39;feature/issue-1042-payment-gateway-refactor&#39;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 2. 一時的に main に切り替えて最新の動作やコードを確認&lt;/span&gt;&lt;br/&gt;
        $ &lt;span style=&quot;color: #38bdf8;&quot;&gt;git switch&lt;/span&gt; main&lt;br/&gt;
        Switched to branch &#39;main&#39;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 3. 確認終了！「git switch -」を打つだけで、長いブランチ名を書かずに直前のブランチへ復帰！&lt;/span&gt;&lt;br/&gt;
        $ &lt;span style=&quot;color: #38bdf8;&quot;&gt;git switch&lt;/span&gt; &lt;span style=&quot;color: #facc15; font-weight: bold;&quot;&gt;-&lt;/span&gt;&lt;br/&gt;
        Switched to branch &#39;feature/issue-1042-payment-gateway-refactor&#39;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 4. もう一度「git switch -」を打てば、今度は main に戻る（2つのブランチを自由に行き来可能）&lt;/span&gt;&lt;br/&gt;
        $ &lt;span style=&quot;color: #38bdf8;&quot;&gt;git switch&lt;/span&gt; &lt;span style=&quot;color: #facc15; font-weight: bold;&quot;&gt;-&lt;/span&gt;&lt;br/&gt;
        Switched to branch &#39;main&#39;
    &lt;/div&gt;

    &lt;p&gt;
        Linuxのシェルで &lt;code&gt;cd -&lt;/code&gt; と打つと直前のディレクトリに戻れるのと全く同じ作法です。&lt;br/&gt;
        従来の &lt;code&gt;git checkout -&lt;/code&gt; でも同様の動作が可能ですが、Git 2.23以降で導入された推奨コマンド &lt;code&gt;git switch -&lt;/code&gt; を使うことで、より明確かつ安全にブランチを行き来できます。
    &lt;/p&gt;

    &lt;!-- セクション④: プロが厳選！日常で最も使う「神エイリアス一覧」 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【図解】プロが厳選！日常で最も使う「神エイリアス一覧」&lt;/h2&gt;
    &lt;p&gt;
        Gitには、任意のコマンドに短い別名（エイリアス）をつける &lt;strong&gt;git config alias&lt;/strong&gt; 機能が標準搭載されています。&lt;br/&gt;
        頻出コマンドを2〜3文字に短縮するだけで、1日のタイピング数が数百打鍵も削減され、ミスタイプも激減します。
    &lt;/p&gt;

    &lt;!-- 図解③ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1YOknkJ5CnlfGZkiULXRcXaHp4G-2yQoO&quot; alt=&quot;プロが厳選！日常で最も使う神エイリアス一覧&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】プロが厳選！日常で最も使う神エイリアス一覧&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        現場のプロエンジニアが常用している代表的な「神エイリアス」の一覧と、その一括登録コマンドをまとめました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #f1f5f9; border-bottom: 2px solid #cbd5e1;&quot;&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 18%;&quot;&gt;エイリアス&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 32%;&quot;&gt;元コマンド&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 50%;&quot;&gt;解説・利用シーン&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold; color: #2563eb;&quot;&gt;&lt;code&gt;git st&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;&lt;code&gt;status -sb&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;現在の変更とブランチを1行要約のショート形式で超高速表示。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold; color: #2563eb;&quot;&gt;&lt;code&gt;git sw&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;&lt;code&gt;switch&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;ブランチ切り替え（&lt;code&gt;git sw main&lt;/code&gt; や &lt;code&gt;git sw -&lt;/code&gt; が打てる）。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold; color: #2563eb;&quot;&gt;&lt;code&gt;git br&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;&lt;code&gt;branch&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;ローカルブランチ一覧の確認。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold; color: #2563eb;&quot;&gt;&lt;code&gt;git cm&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;&lt;code&gt;commit -m&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;メッセージ付きコミットを素早く実行（例: &lt;code&gt;git cm &quot;Fix bug&quot;&lt;/code&gt;）。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold; color: #2563eb;&quot;&gt;&lt;code&gt;git lg&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;&lt;code&gt;log --graph --oneline --decorate --all&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;ブランチの分岐・合流がカラーのアスキーアートで綺麗に一覧できる神ログ。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold; color: #2563eb;&quot;&gt;&lt;code&gt;git df&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;&lt;code&gt;diff&lt;/code&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;変更差分を素早く確認（&lt;code&gt;git df --staged&lt;/code&gt; にも活用）。&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; margin: 20px 0; font-family: Consolas, &#39;Courier New&#39;, monospace; font-size: 14.5px;&quot;&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 神エイリアスを一括登録するコマンド集（ターミナルでそのまま実行可能）&lt;/span&gt;&lt;br/&gt;
        git config --global alias.st &quot;status -sb&quot;&lt;br/&gt;
        git config --global alias.sw switch&lt;br/&gt;
        git config --global alias.br branch&lt;br/&gt;
        git config --global alias.cm &quot;commit -m&quot;&lt;br/&gt;
        git config --global alias.df diff&lt;br/&gt;
        git config --global alias.lg &quot;log --graph --oneline --decorate --all&quot;&lt;br/&gt;
        git config --global alias.unstage &quot;restore --staged&quot;
    &lt;/div&gt;

    &lt;p&gt;
        設定はユーザーのホームディレクトリにある &lt;code&gt;~/.gitconfig&lt;/code&gt;（Windowsでは &lt;code&gt;C:\Users\&amp;lt;ユーザー名&amp;gt;\.gitconfig&lt;/code&gt;）の &lt;code&gt;[alias]&lt;/code&gt; セクションに保存されます。&lt;br/&gt;
        テキストエディタで直接開いて自分好みにカスタマイズすることも可能です。
    &lt;/p&gt;

    &lt;!-- セクション⑤: PowerShell × posh-git によるターミナル状態の「常時可視化」 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【図解】PowerShell × posh-git によるターミナル状態の「常時可視化」&lt;/h2&gt;
    &lt;p&gt;
        Visual Studio付属の「開発者コマンドプロンプト / 開発者PowerShell」や、VS Codeの統合ターミナルを使っているC#エンジニアに絶対に導入してほしいのが、&lt;strong&gt;posh-git&lt;/strong&gt; や &lt;strong&gt;Oh My Posh&lt;/strong&gt; によるプロンプトのGit情報表示です。
    &lt;/p&gt;

    &lt;!-- 図解④ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1nB9bacbzmEHGi2FEdfa7RmDmeHGJznuw&quot; alt=&quot;PowerShell × posh-git によるターミナル状態の常時可視化&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】PowerShell × posh-git によるターミナル状態の常時可視化&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        通常、PowerShellのプロンプトは &lt;code&gt;PS C:\Projects\MySolution&amp;gt;&lt;/code&gt; のようにカレントディレクトリしか表示しません。&lt;br/&gt;
        そのため、「今どのブランチだっけ？」「さっきの編集ファイルはステージングしたっけ？」と確認するために、毎回 &lt;code&gt;git status&lt;/code&gt; を叩く必要があります。&lt;br/&gt;
        &lt;code&gt;posh-git&lt;/code&gt; を導入すると、プロンプト行に以下のようなリッチなステータスバッジが常時リアルタイム表示されます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #e2e8f0; padding: 18px 22px; border-radius: 8px; margin: 20px 0; font-family: Consolas, monospace; font-size: 15px; border-left: 5px solid #10b981;&quot;&gt;
        &lt;code&gt;PS C:\MyApp [&lt;span style=&quot;color: #60a5fa; font-weight: bold;&quot;&gt;main&lt;/span&gt; &lt;span style=&quot;color: #4ade80;&quot;&gt;+1&lt;/span&gt; &lt;span style=&quot;color: #facc15;&quot;&gt;~2&lt;/span&gt; &lt;span style=&quot;color: #f87171;&quot;&gt;-0&lt;/span&gt; &lt;span style=&quot;color: #cbd5e1;&quot;&gt;!&lt;/span&gt;] &amp;gt;&lt;/code&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 16px 20px; margin: 20px 0;&quot;&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;&lt;code style=&quot;color: #2563eb;&quot;&gt;[main]&lt;/code&gt;&lt;/strong&gt;: 現在チェックアウトしているブランチ名&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;&lt;code style=&quot;color: #16a34a;&quot;&gt;+1&lt;/code&gt;（緑色）&lt;/strong&gt;: ステージングに追加されたファイル数（Index）&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;&lt;code style=&quot;color: #ca8a04;&quot;&gt;~2&lt;/code&gt;（黄色）&lt;/strong&gt;: 変更されたが未ステージングのファイル数（Working Tree）&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;&lt;code style=&quot;color: #dc2626;&quot;&gt;-0&lt;/code&gt;（赤色）&lt;/strong&gt;: 削除されたファイル数&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;&lt;code style=&quot;color: #475569;&quot;&gt;!&lt;/code&gt;&lt;/strong&gt;: 未追跡（Untracked）ファイルの存在&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        ターミナルを開いているだけでリポジトリの状態が100%把握できるため、&lt;strong&gt;「誤ってmainブランチに直接コミットしてしまう事故」&lt;/strong&gt;や&lt;strong&gt;「ファイルのステージング漏れ」&lt;/strong&gt;をゼロに抑えることができます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 6px; padding: 16px 20px; margin: 20px 0;&quot;&gt;
        &lt;strong style=&quot;color: #1e40af; font-size: 16px;&quot;&gt;💡 posh-git の超簡単導入手順（PowerShell管理者権限不要）&lt;/strong&gt;
        &lt;ol style=&quot;margin: 8px 0 0 0; padding-left: 22px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;PowerShellで &lt;code&gt;Install-Module posh-git -Scope CurrentUser&lt;/code&gt; を実行&lt;/li&gt;
            &lt;li&gt;プロファイル（&lt;code&gt;notepad $PROFILE&lt;/code&gt;）に &lt;code&gt;Import-Module posh-git&lt;/code&gt; を追記して保存&lt;/li&gt;
            &lt;li&gt;PowerShellを再起動するだけで、Gitリポジトリ内で自動的に美麗プロンプトが表示開始！&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑥: C#現場での実践シナリオ --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ C#現場での実践シナリオ（Visual Studio 統合ターミナルでの高速ワークフロー）&lt;/h2&gt;
    &lt;p&gt;
        C#エンジニアの日々の開発フローにおいて、これらの効率化テクニックがどのように合体して爆速効果を生むのか、具体的な実況シナリオで見てみましょう。
    &lt;/p&gt;

    &lt;div style=&quot;background: #ffffff; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px; margin: 20px 0; box-shadow: 0 1px 3px rgba(0,0,0,0.05);&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; font-size: 18px;&quot;&gt;🚀 実践ワークフロー実況&lt;/h3&gt;
        &lt;ol style=&quot;line-height: 1.9; margin: 0; padding-left: 22px;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;Visual Studioで &lt;code&gt;Ctrl + @&lt;/code&gt;&lt;/strong&gt; を押して統合ターミナル（PowerShell）を開く&lt;/li&gt;
            &lt;li&gt;プロンプトを見るだけで &lt;code&gt;[feature/api-v2 ~1]&lt;/code&gt; と表示されており、変更が1件あることを即認識（&lt;code&gt;git status&lt;/code&gt; 打鍵不要）&lt;/li&gt;
            &lt;li&gt;差分を &lt;code&gt;git df&lt;/code&gt;（2文字）で確認し、C#コードの修正箇所が意図通りであることをチェック&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git add .&lt;/code&gt; して &lt;code&gt;git cm &quot;Refactor UserController&quot;&lt;/code&gt;（エイリアス）で一瞬でコミット&lt;/li&gt;
            &lt;li&gt;「あ、本番の &lt;code&gt;main&lt;/code&gt; で共通モデルの定義を確認したい！」と思い立つ&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git sw main&lt;/code&gt; でサッとmainのコードを確認&lt;/li&gt;
            &lt;li&gt;確認完了後、長いブランチ名を書かずに &lt;strong&gt;&lt;code&gt;git sw -&lt;/code&gt;&lt;/strong&gt;（わずか8キータッチ）で元の作業ブランチへ0.5秒で復帰！&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git lg&lt;/code&gt; で直近のコミットツリーが綺麗につながっていることを視覚的に確認して作業再開&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;p&gt;
        このように、マウス操作や長文コマンドのストレスが一切なく、思考の途切れがゼロになるため、集中力（ゾーン状態）を維持したまま快適にコーディングを進めることができます。
    &lt;/p&gt;

    &lt;!-- まとめセクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;📌 本日のまとめ・理解したい重要ポイント&lt;/h2&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #e2e8f0; border-radius: 8px; padding: 22px 24px; margin: 25px 0;&quot;&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; line-height: 1.95; font-size: 16px;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;直前ブランチへの瞬間移動（&lt;code&gt;git switch -&lt;/code&gt;）:&lt;/strong&gt;&lt;br/&gt;
                リモコンの「前チャンネル」ボタン感覚で、長いブランチ名を打たずに直前のブランチへワンタッチ復帰できる。mainブランチとの一時的な行き来に必須！&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;神エイリアスで打鍵数を80%削減:&lt;/strong&gt;&lt;br/&gt;
                &lt;code&gt;st (status)&lt;/code&gt;、&lt;code&gt;sw (switch)&lt;/code&gt;、&lt;code&gt;br (branch)&lt;/code&gt;、&lt;code&gt;cm (commit -m)&lt;/code&gt;、&lt;code&gt;lg (graph log)&lt;/code&gt; など、頻出コマンドを2〜3文字に短縮してミスと疲労を一掃する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;PowerShell × posh-git によるプロンプト常時可視化:&lt;/strong&gt;&lt;br/&gt;
                現在のブランチ名、ステージング件数、変更件数をプロンプトに常時カラーバッジ表示。確認コマンドの実行回数を大幅に削減し、main直コミット事故も完全防止。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;思考のスピードでコードを書く:&lt;/strong&gt;&lt;br/&gt;
                C#開発においてキーボードホームポジションを維持し、タイピングとマウスの無駄を徹底的に排除することが、プロとしての高い生産性を支える基盤となる。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #3b82f6; padding: 18px 20px; margin: 30px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #1e40af; font-size: 17px;&quot;&gt;次回予告 【Day 33】&lt;/strong&gt;&lt;br/&gt;
        &lt;span style=&quot;font-size: 15.5px; color: #334155;&quot;&gt;
            次回は、作業中の未コミット変更を一時的に安全な棚へ退避させ、緊急のバグ修正やブランチ切り替えを可能にする救世主テクニック、&lt;strong&gt;「git stash（スタッシュ）の基本と応用」&lt;/strong&gt;をお届けします！ お楽しみに！
        &lt;/span&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/4239404671301531311/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-32git-switch-10.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4239404671301531311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4239404671301531311'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-32git-switch-10.html' title='【Day 32】git switch - やエイリアス設定で日常操作を10倍爆速化する'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1Zs0GuXoQWCHCl7iuyIFL7nEtpn1kMf39=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-4049615590874856308</id><published>2026-10-30T09:10:00.457+09:00</published><updated>2026-10-30T09:10:00.457+09:00</updated><title type='text'>【Day 34】ポートマッピング（-p 8080:80）とポート競合の解決法 〜ホストとコンテナを繋ぐポートフォワーディングの原理・IIS（80）/SQL Server（1433）衝突回避・PowerShellポート調査術・.env変数化によるC#チーム開発ベストプラクティス〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1GT8Kd-_fJTVrb84y7018k-ty1LbnX6ac&quot; alt=&quot;Day 34 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 34: ポートマッピング（-p 8080:80）とポート競合の解決法&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 導入メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: linear-gradient(135deg, #e0f2fe 0%, #f0fdf4 100%); border-left: 6px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0; box-shadow: 0 4px 12px rgba(13,183,237,0.08);&quot;&gt;
        &lt;div style=&quot;font-size: 32px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;font-size: 15.5px; color: #0f172a;&quot;&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; font-weight: bold; color: #0369a1; font-size: 17px;&quot;&gt;「コンテナを起動しようとしたら『Ports are not available: bind: address already in use』で失敗した！？ ホストとコンテナのポートってどう繋がっているの？」&lt;/p&gt;
            &lt;p style=&quot;margin: 0; line-height: 1.8;&quot;&gt;
                前回（Day 33）は、Docker内蔵DNS（127.0.0.11）とサービス名通信によって「IPアドレスを覚えなくてよい世界」を学びました。&lt;br/&gt;
                しかし、次に立ちはだかるのが&lt;strong&gt;「外部ブラウザやホストPCからコンテナへどうやってアクセスするのか？」&lt;/strong&gt;というポートの壁です。&lt;br/&gt;
                &lt;em&gt;「物理サーバーやオンプレミスVMなら、各マシンが独自のIPアドレスを持っていたので、どのサーバーでも80番や1433番ポートを独占して待ち受けることができた。&lt;br/&gt;
                だが開発用Windows PC上でDockerを動かすと、既存のIIS（80番）やSQL Server（1433番）と衝突してコンテナが起動しない！ `-p 8080:80` ってどっちが外側でどっちが内側なの？」&lt;/em&gt;&lt;br/&gt;
                本講義では、ポートフォワーディングの根本原理から、Windowsでのポート競合調査術、そしてチーム開発で絶対に衝突しない &lt;code&gt;.env&lt;/code&gt; を使った柔軟なC#現場設計までを徹底解説します！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 目次ブロック --&gt;
    &lt;div style=&quot;background-color: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 24px; margin-bottom: 35px;&quot;&gt;
        &lt;h3 style=&quot;margin-top: 0; margin-bottom: 14px; font-size: 18px; color: #0f172a; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;color: #0db7ed; margin-right: 8px;&quot;&gt;📑&lt;/span&gt; 本講義のロードマップ
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #334155; font-size: 15px; line-height: 2;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;第1章：ポートマッピング（-p）の原理&lt;/strong&gt; 〜ホスト受付口とコンテナ実サービスの対応関係〜&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第2章：現場で最も起きる「ポート重複エラー」の正体&lt;/strong&gt; 〜IIS（80）＆ローカルSQL Server（1433）の激突〜&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第3章：PowerShellによるポート競合調査術&lt;/strong&gt; 〜ポートを占有する犯人プロセスの特定と解除〜&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第4章：C#/.NET 現場実践：.envを活用した柔軟なポート設計&lt;/strong&gt; 〜チーム全員が衝突しないGit運用〜&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第5章：現場の落とし穴&lt;/strong&gt; 〜コンテナ間通信でホストポートを使ってしまうミス〜&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第6章：第7部核心！理解度チェッククイズ&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第1章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 50%; width: 32px; height: 32px; display: inline-flex; justify-content: center; align-items: center; font-size: 16px; margin-right: 12px;&quot;&gt;1&lt;/span&gt;
        ポートマッピング（-p）の原理 〜ホスト受付口とコンテナ実サービスの対応関係〜
    &lt;/h2&gt;

    &lt;p&gt;
        Dockerコンテナは、ホストOSとは独立した仮想ネットワーク空間（Network Namespace）の中で動作しています。&lt;br/&gt;
        そのため、&lt;strong&gt;何も指定せずにコンテナを起動しただけでは、ホストPCのブラウザからコンテナ内部のWebサーバーにアクセスすることはできません。&lt;/strong&gt;
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1UEE-zDbfKZLwA-CHy-AvDT3lp25H-AEI&quot; alt=&quot;ポートフォワーディングの仕組み&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】ホスト受付窓口（外側）からコンテナ実サービス（内側）へのポートフォワーディングの仕組み&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 30px;&quot;&gt;「ホストポート : コンテナポート」の絶対ルール&lt;/h3&gt;
    &lt;p&gt;
        ホストPC（Windowsなど）のポートとコンテナ内部のポートを結びつけるのが &lt;code&gt;-p&lt;/code&gt;（ポートフォワーディング）オプションです。&lt;br/&gt;
        書式は以下の通り、&lt;strong&gt;「外側（ホスト）：内側（コンテナ）」&lt;/strong&gt;の順序になります。
    &lt;/p&gt;

    &lt;div style=&quot;background-color: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14.5px; margin: 20px 0; overflow-x: auto;&quot;&gt;
# -p &lt;ホストポート&gt;:&lt;コンテナポート&gt;
docker run -d -p 8080:80 --name my-web nginx
    &lt;/div&gt;

    &lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 25px 0; font-size: 15px;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background-color: #0284c7; color: white;&quot;&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1;&quot;&gt;要素&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1;&quot;&gt;ポート番号&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1;&quot;&gt;役割と意味&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr style=&quot;background-color: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;ホストポート（外側）&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; color: #0284c7; font-weight: bold;&quot;&gt;8080&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;開発者がブラウザで &lt;code&gt;http://localhost:8080&lt;/code&gt; と叩く際の受付窓口。ホストOSのポート重複制限を受ける。&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;コンテナポート（内側）&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; color: #10b981; font-weight: bold;&quot;&gt;80&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;コンテナ内部でWebサーバー（nginxやKestrel）が実際にリッスンしているポート。隔離されているため常に標準ポート（80や1433）でOK。&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;div style=&quot;background-color: #eff6ff; border-left: 4px solid #3b82f6; padding: 14px 18px; margin: 20px 0; border-radius: 4px; font-size: 15px;&quot;&gt;
        &lt;strong&gt;💡 セキュリティの鉄則：ローカルループバック限定バインド&lt;/strong&gt;&lt;br/&gt;
        &lt;code&gt;-p 8080:80&lt;/code&gt; と書くと、ホストPCがLANに接続している場合、同一Wi-Fi内の同僚PCからも &lt;code&gt;http://あなたのIP:8080&lt;/code&gt; でコンテナにアクセスできてしまいます。&lt;br/&gt;
        自分のPCからのみアクセスを許可したい場合は、&lt;code&gt;-p 127.0.0.1:8080:80&lt;/code&gt; のようにホストIPを明示的に &lt;code&gt;127.0.0.1&lt;/code&gt; にバインドするのが安全な開発現場のベストプラクティスです。
    &lt;/div&gt;

    &lt;!-- 第2章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 50%; width: 32px; height: 32px; display: inline-flex; justify-content: center; align-items: center; font-size: 16px; margin-right: 12px;&quot;&gt;2&lt;/span&gt;
        現場で最も起きる「ポート重複エラー」の正体 〜IIS＆SQL Serverの激突〜
    &lt;/h2&gt;

    &lt;p&gt;
        Dockerを導入したWindowsエンジニアが最初に直面するエラーの第1位が、この&lt;strong&gt;「ポート重複エラー（bind: address already in use）」&lt;/strong&gt;です。
    &lt;/p&gt;

    &lt;div style=&quot;background-color: #fef2f2; border: 1px solid #fecaca; border-left: 5px solid #ef4444; padding: 16px 20px; border-radius: 6px; margin: 20px 0;&quot;&gt;
        &lt;strong style=&quot;color: #b91c1c; font-size: 16px;&quot;&gt;⚠️ 実際に出現するエラーメッセージ&lt;/strong&gt;
        &lt;pre style=&quot;margin: 8px 0 0 0; color: #991b1b; font-family: Consolas, monospace; font-size: 13.5px; white-space: pre-wrap;&quot;&gt;
docker: Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:80 -&gt; 0.0.0.0:0: listen tcp 0.0.0.0:80: bind: address already in use.
        &lt;/pre&gt;
    &lt;/div&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1Ja8veGns8pVXaO9SXANnwLntVRUvaVvT&quot; alt=&quot;ポート重複エラーの正体と解決&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】旧来のIIS・SQL ServerとDockerの衝突原因とポート変更による完全共存&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 30px;&quot;&gt;Windows開発機に潜む「ポート占有の主」たち&lt;/h3&gt;
    &lt;p&gt;
        なぜ80番や1433番でコンテナを起動しようとすると落ちるのでしょうか？&lt;br/&gt;
        それは、Windows開発機に最初からインストールされているサービスが、すでにそのポートを「独占」して待ち受けているからです。
    &lt;/p&gt;

    &lt;ul style=&quot;padding-left: 20px; line-height: 2;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;ポート 80番の代表格：&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;&lt;strong&gt;IIS（World Wide Web 発行サービス / W3SVC）：&lt;/strong&gt; 長年ASP.NET Web Formsや.NET Frameworkアプリを動かしてきたWindowsのWebサーバー。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;SQL Server Reporting Services (SSRS)：&lt;/strong&gt; レポート配信サービスが80番を掴んでいるケースも多発。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;システムプロセス（PID 4 / HTTP.sys）：&lt;/strong&gt; WindowsカーネルのHTTPリスナーが予約している場合。&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;ポート 1433番の代表格：&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;&lt;strong&gt;ローカルのSQL Server インスタンス（MSSQLSERVER）：&lt;/strong&gt; WindowsのローカルサービスとしてSQL Server ExpressやDeveloper Editionが常駐している場合。&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;

    &lt;div style=&quot;background-color: #f0fdf4; border-left: 4px solid #10b981; padding: 14px 18px; margin: 20px 0; border-radius: 4px; font-size: 15px;&quot;&gt;
        &lt;strong&gt;✅ 解決の王道：コンテナの設定は変えず、ホスト側の受付番号をずらす！&lt;/strong&gt;&lt;br/&gt;
        「IISをアンインストールしなければならないのか？」と焦る必要は一切ありません。&lt;br/&gt;
        コンテナ側のポート（80や1433）はいじらず、ホスト側の受付ポートを &lt;code&gt;-p 8080:80&lt;/code&gt; や &lt;code&gt;-p 14333:1433&lt;/code&gt; に変更するだけで、既存のIISやローカルSQL ServerとDockerコンテナを何の問題もなく完全共存させることができます。
    &lt;/div&gt;

    &lt;!-- 第3章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 50%; width: 32px; height: 32px; display: inline-flex; justify-content: center; align-items: center; font-size: 16px; margin-right: 12px;&quot;&gt;3&lt;/span&gt;
        PowerShellによるポート競合調査術 〜ポートを占有する犯人プロセスの特定と解除〜
    &lt;/h2&gt;

    &lt;p&gt;
        「どうしてもホストの80番を使いたい」「そもそもどのソフトがポートを握っているのか知りたい」という場合、PowerShellを使った確実な調査手順が必須スキルになります。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1McSrdsH_d0Pc-aff_k5RPji4Rx2pDz3o&quot; alt=&quot;競合ポートの調査手順&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】PowerShellでポートを占有する犯人プロセスを特定する3ステップ&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 30px;&quot;&gt;ポート特定と停止の3ステップコマンド&lt;/h3&gt;

    &lt;div style=&quot;background-color: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 20px 0; overflow-x: auto;&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;# 【Step 1】 80番ポートを開いている接続とプロセスID（PID）を確認&lt;/span&gt;
Get-NetTCPConnection -LocalPort 80 | Select-Object LocalAddress, LocalPort, State, OwningProcess

&lt;span style=&quot;color: #64748b;&quot;&gt;# ※ 従来のコマンドプロンプトや古いWindowsの場合はこちら&lt;/span&gt;
netstat -ano | findstr :80

&lt;span style=&quot;color: #64748b;&quot;&gt;# 【Step 2】 判明したPID（例: 4120）からプロセス名とサービスを特定&lt;/span&gt;
Get-Process -Id 4120 | Select-Object Id, ProcessName, Description, Path

&lt;span style=&quot;color: #64748b;&quot;&gt;# 【Step 3】 犯人がIIS（W3SVC）だった場合、一時停止してポートを解放&lt;/span&gt;
Stop-Service W3SVC
&lt;span style=&quot;color: #64748b;&quot;&gt;# またはコマンドラインから: iisreset /stop&lt;/span&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background-color: #fffbeb; border-left: 4px solid #f59e0b; padding: 14px 18px; margin: 20px 0; border-radius: 4px; font-size: 15px;&quot;&gt;
        &lt;strong&gt;💡 PID 4（System / HTTP.sys）が80番を握っている場合の豆知識&lt;/strong&gt;&lt;br/&gt;
        PIDが &lt;code&gt;4&lt;/code&gt;（System）になっている場合、WindowsカーネルのHTTP.sysドライバーがURL予約を保持しています。&lt;br/&gt;
        管理者PowerShellで &lt;code&gt;netsh http show servicestate&lt;/code&gt; を実行すると、どのサービス（Windows Remote ManagementやBranchCacheなど）がHTTP.sys経由で80番を要求しているかを一発で特定できます。
    &lt;/div&gt;

    &lt;!-- 第4章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 50%; width: 32px; height: 32px; display: inline-flex; justify-content: center; align-items: center; font-size: 16px; margin-right: 12px;&quot;&gt;4&lt;/span&gt;
        C#/.NET 現場実践：.envを活用した柔軟なポート設計 〜チーム全員が衝突しないGit運用〜
    &lt;/h2&gt;

    &lt;p&gt;
        チーム開発において、&lt;code&gt;docker-compose.yml&lt;/code&gt; にポート番号を &lt;code&gt;&quot;8080:80&quot;&lt;/code&gt; と直接ハードコードしてGitコミットしてしまうと、現場は大混乱に陥ります。&lt;br/&gt;
        &lt;em&gt;「AさんのPCは8080が空いているが、BさんのPCでは別プロジェクトで8080が稼働中」「CさんはローカルSQL Serverがあるから1433を14333に変えたい」&lt;/em&gt;といった個人のPC環境差異があるためです。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1sP9c5tOMSk_PfmWCwZ5jsiARwyJqvlvJ&quot; alt=&quot;C#現場実践：.envで柔軟なポート設計&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】docker-compose.ymlと.envによるチーム開発でのポート衝突回避アーキテクチャ&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 30px;&quot;&gt;Git管理の黄金設計：デフォルト値付き変数構文&lt;/h3&gt;
    &lt;p&gt;
        Docker Composeでは、&lt;code&gt;${変数名:-デフォルト値}&lt;/code&gt; という構文を使うことで、「基本は8080番、各自の都合があれば &lt;code&gt;.env&lt;/code&gt; で上書き可能」という理想の運用を実現できます。
    &lt;/p&gt;

    &lt;div style=&quot;background-color: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 20px 0; overflow-x: auto;&quot;&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;# docker-compose.yml （Gitで全員共有するファイル）&lt;/span&gt;
&lt;span style=&quot;color: #f59e0b;&quot;&gt;version&lt;/span&gt;: &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&#39;3.8&#39;&lt;/span&gt;

&lt;span style=&quot;color: #f59e0b;&quot;&gt;services&lt;/span&gt;:
  &lt;span style=&quot;color: #f59e0b;&quot;&gt;web-api&lt;/span&gt;:
    &lt;span style=&quot;color: #f59e0b;&quot;&gt;build&lt;/span&gt;:
      &lt;span style=&quot;color: #f59e0b;&quot;&gt;context&lt;/span&gt;: .
      &lt;span style=&quot;color: #f59e0b;&quot;&gt;dockerfile&lt;/span&gt;: Dockerfile
    &lt;span style=&quot;color: #f59e0b;&quot;&gt;ports&lt;/span&gt;:
      &lt;span style=&quot;color: #64748b;&quot;&gt;# WEB_PORTが未定義なら8080を使用。コンテナ内は80番固定！&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;${WEB_PORT:-8080}:80&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #f59e0b;&quot;&gt;environment&lt;/span&gt;:
      - ASPNETCORE_ENVIRONMENT=Development
      - ConnectionStrings__SqlDb=Server=sqlserver,1433;Database=OrderDb;User Id=sa;Password=Your_Password123;TrustServerCertificate=True;
    &lt;span style=&quot;color: #f59e0b;&quot;&gt;depends_on&lt;/span&gt;:
      - sqlserver

  &lt;span style=&quot;color: #f59e0b;&quot;&gt;sqlserver&lt;/span&gt;:
    &lt;span style=&quot;color: #f59e0b;&quot;&gt;image&lt;/span&gt;: mcr.microsoft.com/mssql/server:2022-latest
    &lt;span style=&quot;color: #f59e0b;&quot;&gt;ports&lt;/span&gt;:
      &lt;span style=&quot;color: #64748b;&quot;&gt;# ホストのSQL Serverとぶつからないよう、デフォルトを14333に設定&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;${DB_PORT:-14333}:1433&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #f59e0b;&quot;&gt;environment&lt;/span&gt;:
      - ACCEPT_EULA=Y
      - MSSQL_SA_PASSWORD=Your_Password123
    &lt;/div&gt;

    &lt;div style=&quot;background-color: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 20px 0; overflow-x: auto;&quot;&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;# .env.example （Gitにコミットして共有するひな形）&lt;/span&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;# 各自の環境でポートが競合する場合はコピーして .env を作成し、数値を変更してください&lt;/span&gt;
WEB_PORT=8080
DB_PORT=14333

&lt;span style=&quot;color: #38bdf8;&quot;&gt;# -------------------------------------------------------------&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;# .env （各個人のローカルファイル：.gitignoreに必ず追加！）&lt;/span&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;# 例: Bさんは8080が使われているので8081に変更して起動&lt;/span&gt;
WEB_PORT=8081
DB_PORT=14333
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 30px;&quot;&gt;C# (.NET 8/9) 側での確認実装例&lt;/h3&gt;
    &lt;p&gt;
        ASP.NET Core Web API側では、コンテナ内部でどのポートをリッスンしているかに関係なく、&lt;code&gt;http://localhost:8080/api/info&lt;/code&gt;（または各自のポート）で正常にレスポンスを返せます。
    &lt;/p&gt;

    &lt;div style=&quot;background-color: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 20px 0; overflow-x: auto;&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;// Program.cs (.NET 8 Minimal API)&lt;/span&gt;
&lt;span style=&quot;color: #f59e0b;&quot;&gt;var&lt;/span&gt; builder = WebApplication.CreateBuilder(args);
&lt;span style=&quot;color: #f59e0b;&quot;&gt;var&lt;/span&gt; app = builder.Build();

app.MapGet(&lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;/api/info&quot;&lt;/span&gt;, (IConfiguration config) =&gt;
{
    &lt;span style=&quot;color: #f59e0b;&quot;&gt;return&lt;/span&gt; Results.Ok(&lt;span style=&quot;color: #f59e0b;&quot;&gt;new&lt;/span&gt;
    {
        MachineName = Environment.MachineName,
        Environment = Environment.GetEnvironmentVariable(&lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;ASPNETCORE_ENVIRONMENT&quot;&lt;/span&gt;),
        Message = &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;ポートマッピング経由での接続に成功しました！&quot;&lt;/span&gt;,
        TimestampUtc = DateTime.UtcNow
    });
});

app.Run();
    &lt;/div&gt;

    &lt;!-- 第5章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 50%; width: 32px; height: 32px; display: inline-flex; justify-content: center; align-items: center; font-size: 16px; margin-right: 12px;&quot;&gt;5&lt;/span&gt;
        現場の落とし穴：コンテナ間通信でホストポートを使ってしまうミス
    &lt;/h2&gt;

    &lt;div style=&quot;background-color: #fff1f2; border: 1px solid #fecdd3; border-radius: 8px; padding: 20px 24px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #e11d48; font-size: 17px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;margin-right: 8px;&quot;&gt;🚨&lt;/span&gt; 初心者が絶対にハマる「ポートの指定先勘違い」
        &lt;/h4&gt;
        &lt;p style=&quot;margin: 0; line-height: 1.8; color: #334155;&quot;&gt;
            ホストのポートを &lt;code&gt;14333:1433&lt;/code&gt; にマッピングした際、C# Web APIからDBへの接続文字列に &lt;code&gt;Server=sqlserver,14333&lt;/code&gt; と書いてしまい接続エラーになるケースが多発します！&lt;br/&gt;
            &lt;strong&gt;コンテナ同士が同一ネットワーク内で通信する場合は、ホスト側のポート（14333）は一切無関係です。&lt;/strong&gt;&lt;br/&gt;
            コンテナ間通信では、コンテナ内部ポート（1433）とサービス名（&lt;code&gt;sqlserver&lt;/code&gt;）をそのまま使用してください（Day 33で学んだDocker内蔵DNSが直接ルーティングします）。&lt;br/&gt;
            ホストポート（14333）を使うのは、&lt;strong&gt;ホストPC上のSQL Server Management Studio (SSMS) や外部ツールから接続する時だけ&lt;/strong&gt;です！
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第6章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 50%; width: 32px; height: 32px; display: inline-flex; justify-content: center; align-items: center; font-size: 16px; margin-right: 12px;&quot;&gt;6&lt;/span&gt;
        第7部核心！理解度チェッククイズ
    &lt;/h2&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 22px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;margin-top: 0; color: #0f172a; font-size: 16.5px;&quot;&gt;【第1問】 コマンド &lt;code&gt;docker run -p 5000:80 nginx&lt;/code&gt; を実行した場合、ホストPCのブラウザからアクセスする正しいURLはどれ？&lt;/h4&gt;
        &lt;ul style=&quot;list-style: none; padding-left: 0; line-height: 2;&quot;&gt;
            &lt;li&gt;A. &lt;code&gt;http://localhost:80&lt;/code&gt;&lt;/li&gt;
            &lt;li&gt;B. &lt;code&gt;http://localhost:5000&lt;/code&gt;&lt;/li&gt;
            &lt;li&gt;C. &lt;code&gt;http://localhost:5080&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
        &lt;details style=&quot;margin-top: 10px; background: #ffffff; padding: 12px 16px; border-radius: 6px; border: 1px solid #e2e8f0;&quot;&gt;
            &lt;summary style=&quot;font-weight: bold; color: #0284c7; cursor: pointer;&quot;&gt;正解と解説を見る&lt;/summary&gt;
            &lt;p style=&quot;margin: 8px 0 0 0; font-size: 14.5px; line-height: 1.8;&quot;&gt;
                &lt;strong&gt;正解：B（http://localhost:5000）&lt;/strong&gt;&lt;br/&gt;
                &lt;code&gt;-p &lt;ホストポート&gt;:&lt;コンテナポート&gt;&lt;/code&gt; の順序です。ホスト側で待ち受けるポートはコロンの左側である &lt;code&gt;5000&lt;/code&gt; になります。
            &lt;/p&gt;
        &lt;/details&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 22px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;margin-top: 0; color: #0f172a; font-size: 16.5px;&quot;&gt;【第2問】 既存のIISがポート80番を使用しているWindows環境で、DockerのWebコンテナ（内部80番）を共存させる最も推奨されるアプローチは？&lt;/h4&gt;
        &lt;ul style=&quot;list-style: none; padding-left: 0; line-height: 2;&quot;&gt;
            &lt;li&gt;A. IISをアンインストールし、WindowsのWeb機能を完全に無効化する&lt;/li&gt;
            &lt;li&gt;B. コンテナ内部のDockerfileやnginx設定を書き換えて8080番リッスンに変更する&lt;/li&gt;
            &lt;li&gt;C. コンテナの設定はそのままで、ホスト側のマッピングポートを &lt;code&gt;8080:80&lt;/code&gt; にずらす&lt;/li&gt;
        &lt;/ul&gt;
        &lt;details style=&quot;margin-top: 10px; background: #ffffff; padding: 12px 16px; border-radius: 6px; border: 1px solid #e2e8f0;&quot;&gt;
            &lt;summary style=&quot;font-weight: bold; color: #0284c7; cursor: pointer;&quot;&gt;正解と解説を見る&lt;/summary&gt;
            &lt;p style=&quot;margin: 8px 0 0 0; font-size: 14.5px; line-height: 1.8;&quot;&gt;
                &lt;strong&gt;正解：C&lt;/strong&gt;&lt;br/&gt;
                コンテナ内部は独立した名前空間なので標準の80番のままで問題ありません。ホスト側のポートを &lt;code&gt;8080&lt;/code&gt; などの空きポートにマッピングするだけで、IISとDockerは平和に共存できます。
            &lt;/p&gt;
        &lt;/details&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 22px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;margin-top: 0; color: #0f172a; font-size: 16.5px;&quot;&gt;【第3問】 チーム開発で開発者ごとのポート重複を防ぐため、docker-compose.yml と .env をどのように組み合わせるべきか？&lt;/h4&gt;
        &lt;ul style=&quot;list-style: none; padding-left: 0; line-height: 2;&quot;&gt;
            &lt;li&gt;A. docker-compose.yml にポート番号を直接ハードコードし、衝突した人が都度書き換えてコミットする&lt;/li&gt;
            &lt;li&gt;B. docker-compose.yml に &lt;code&gt;&quot;${WEB_PORT:-8080}:80&quot;&lt;/code&gt; と定義し、個人の競合は &lt;code&gt;.env&lt;/code&gt; で上書きする（.envは.gitignoreに追加）&lt;/li&gt;
            &lt;li&gt;C. ポートマッピングは一切使わず、全員がホストネットワーク（network_mode: host）で動かす&lt;/li&gt;
        &lt;/ul&gt;
        &lt;details style=&quot;margin-top: 10px; background: #ffffff; padding: 12px 16px; border-radius: 6px; border: 1px solid #e2e8f0;&quot;&gt;
            &lt;summary style=&quot;font-weight: bold; color: #0284c7; cursor: pointer;&quot;&gt;正解と解説を見る&lt;/summary&gt;
            &lt;p style=&quot;margin: 8px 0 0 0; font-size: 14.5px; line-height: 1.8;&quot;&gt;
                &lt;strong&gt;正解：B&lt;/strong&gt;&lt;br/&gt;
                デフォルト値付き環境変数構文 &lt;code&gt;${WEB_PORT:-8080}&lt;/code&gt; を使い、Git共有するファイルは共通化しつつ、個人のローカル都合は &lt;code&gt;.env&lt;/code&gt; に逃がすのが現場のベストプラクティスです。
            &lt;/p&gt;
        &lt;/details&gt;
    &lt;/div&gt;

    &lt;!-- まとめブロック --&gt;
    &lt;div style=&quot;background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); color: #ffffff; border-radius: 12px; padding: 28px 30px; margin-top: 50px; box-shadow: 0 10px 25px rgba(0,0,0,0.15);&quot;&gt;
        &lt;h3 style=&quot;margin-top: 0; color: #38bdf8; font-size: 20px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;margin-right: 10px;&quot;&gt;🎯&lt;/span&gt; 本講義の最重要まとめ（チェックリスト）
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 15px 0 0 0; padding-left: 20px; line-height: 2; font-size: 15.5px; color: #e2e8f0;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;「ホスト：コンテナ」の順序：&lt;/strong&gt; &lt;code&gt;-p 8080:80&lt;/code&gt; は「ホストの8080番をコンテナの80番にフォワードする」。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;コンテナ内部は標準ポートで固定：&lt;/strong&gt; 内部をわざわざ8080に変える必要はない。外側だけを柔軟にずらせばよい。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;ポート競合はPowerShellで特定：&lt;/strong&gt; &lt;code&gt;Get-NetTCPConnection -LocalPort 80&lt;/code&gt; と &lt;code&gt;Get-Process&lt;/code&gt; で犯人プロセスを瞬時に特定可能。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Git運用の鉄則：&lt;/strong&gt; &lt;code&gt;docker-compose.yml&lt;/code&gt; には &lt;code&gt;${WEB_PORT:-8080}&lt;/code&gt; と書き、各員のPC環境差異は &lt;code&gt;.env&lt;/code&gt; で吸収する。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background-color: #f8fafc; border: 2px dashed #0db7ed; border-radius: 10px; padding: 22px 24px; margin-top: 40px; text-align: center;&quot;&gt;
        &lt;span style=&quot;background-color: #0db7ed; color: #ffffff; font-weight: bold; font-size: 13px; padding: 4px 12px; border-radius: 20px; text-transform: uppercase;&quot;&gt;Next Lecture&lt;/span&gt;
        &lt;h3 style=&quot;margin: 12px 0 8px 0; color: #0f172a; font-size: 19px;&quot;&gt;
            Day 35：コンテナのヘルスチェック（HEALTHCHECK）と依存関係の制御 〜DB起動待ち問題の完全解決〜
        &lt;/h3&gt;
        &lt;p style=&quot;margin: 0; color: #475569; font-size: 15px; line-height: 1.8;&quot;&gt;
            次回は、コンテナが「起動した（Running）」と「本当にリクエストを受け付けられる（Healthy）」の違いを学びます。&lt;br/&gt;
            SQL ServerやMySQLの起動が完了する前にC# Web APIが立ち上がってDB接続エラーでクラッシュする「起動順序問題」を、HEALTHCHECKとdepends_on条件でエレガントに解決する実践技を完全攻略します！ お楽しみに！
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/4049615590874856308/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-34-p-808080-iis80sql.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4049615590874856308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4049615590874856308'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-34-p-808080-iis80sql.html' title='【Day 34】ポートマッピング（-p 8080:80）とポート競合の解決法 〜ホストとコンテナを繋ぐポートフォワーディングの原理・IIS（80）/SQL Server（1433）衝突回避・PowerShellポート調査術・.env変数化によるC#チーム開発ベストプラクティス〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1GT8Kd-_fJTVrb84y7018k-ty1LbnX6ac=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-3351522459389581503</id><published>2026-10-29T18:06:09.609+09:00</published><updated>2026-10-29T18:06:09.609+09:00</updated><title type='text'>【Day 31】git rerere で過去に解決したコンフリクトを全自動解決させる魔法</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1Ct0xLvaPRtfaZvXiwXdHELAmACYeLHFL&quot; alt=&quot;Day 31 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 31】git rerere で過去に解決したコンフリクトを全自動解決させる魔法&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 30では、全リポジトリのコミット差分から消えた過去の関数や定数を0.1秒で掘り当てる&lt;strong&gt;「git log -S（つるはし検索）」&lt;/strong&gt;の神技を学びました。&lt;br/&gt;
            そして本日のDay 31は、チーム開発や長期ブランチ運用において全エンジニアが一度は激しいストレスを感じるあの悩み——&lt;br/&gt;
            &lt;strong&gt;「毎朝 main をリベース（マージ）するたび、昨日と全く同じコンフリクトを何度も手作業で解かされる……！」&lt;/strong&gt;&lt;br/&gt;
            という無駄な作業をこの世から完全に消滅させる奇跡の魔法——&lt;br/&gt;
            &lt;strong&gt;【git rerere で過去に解決したコンフリクトを全自動解決させる魔法】&lt;/strong&gt;を徹底解説します！&lt;br/&gt;
            &lt;strong&gt;rerere&lt;/strong&gt; とは、&lt;strong&gt;「Reuse Recorded Resolution（記録された解決の再利用）」&lt;/strong&gt;の略称です。&lt;br/&gt;
            この機能を有効にしておくだけで、Gitはあなたが一度手動で解いたコンフリクトの「衝突パターン」と「解決結果」を裏側で自動記憶します。&lt;br/&gt;
            そして次回以降、全く同じコードの衝突が発生した瞬間に、&lt;strong&gt;人間が何もしなくてもGitが全自動でマージを完了&lt;/strong&gt;してくれるのです！&lt;br/&gt;
            C#ソリューションでのNuGet依存関係の競合や共通設定ファイルの衝突など、現場の消耗を一掃するプロの必須テクニックを身につけましょう！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        複数人で開発を進めていると、数週間〜数ヶ月に及ぶ長期フィーチャーブランチを運用することがあります。&lt;br/&gt;
        最新の &lt;code&gt;main&lt;/code&gt; ブランチの変更を取り込もうと &lt;code&gt;git rebase main&lt;/code&gt; や &lt;code&gt;git merge main&lt;/code&gt; を行うたびに、まったく同じファイルの同じ行でコンフリクトが発生し、何度も同じ解消作業を繰り返した経験はないでしょうか？&lt;br/&gt;
        これは開発者の集中力を削ぎ、誤ったマージによるバグ混入のリスクを高める重大な原因です。&lt;br/&gt;
        Gitに備わっている &lt;strong&gt;git rerere&lt;/strong&gt; を活用すれば、過去の解決結果が自動適用され、コンフリクト解決の苦痛から完全に解放されます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;code&gt;git rerere&lt;/code&gt;（Reuse Recorded Resolution）の基本概念と絶大な自動化メリットを理解する&lt;/li&gt;
            &lt;li&gt;手動解決の繰り返しによる人的ミスやストレスがなぜ発生するのか、その構造的課題を把握する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git rerere&lt;/code&gt; の動作フロー（記録開始 → 初回手動解決 → 自動解決適用）の3ステップを完全習得する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git config --global rerere.enabled true&lt;/code&gt; による環境設定と &lt;code&gt;.git/rr-cache/&lt;/code&gt; の内部構造を理解する&lt;/li&gt;
            &lt;li&gt;C#プロジェクト（.csprojのNuGet更新や共通ヘッダー）における実践的なコンフリクト自動解決ノウハウを体得する&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: 何度も同じ競合を手動解決する苦痛 vs git rerereの自動解決 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】何度も同じ競合を手動解決する苦痛 vs git rerereの自動解決&lt;/h2&gt;
    &lt;p&gt;
        まずは、従来の開発フローと &lt;code&gt;git rerere&lt;/code&gt; を導入した後の世界の違いを図解で見てみましょう。
    &lt;/p&gt;

    &lt;!-- 図解① --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1h6m_37ekfN0EYGQZp30SBE8FVPr3TWvB&quot; alt=&quot;何度も同じ競合を手動解決する苦痛 vs git rerereの自動解決&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】毎日のリベースやブランチ統合で同じ衝突を手作業で解く苦痛 vs 一度解けば次回からGitが瞬時に自動解消するgit rerere&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        SVNや従来のGit運用では、ブランチを長期間分岐させたまま何度も同期をとる際、同じ衝突を毎回手作業でエディタを開いて解消する必要がありました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15.5px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #f1f5f9; border-bottom: 2px solid #cbd5e1;&quot;&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 22%;&quot;&gt;比較項目&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 38%; color: #991b1b;&quot;&gt;従来のコンフリクト対応&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 40%; color: #1e40af;&quot;&gt;git rerere 有効時の対応&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;リベース/マージの反復&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;同じ衝突が起きるたびに処理がストップし、手作業で解消してコミットが必要。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;過去の解消パターンと一致した瞬間、Gitが0秒で自動解消してそのまま進行。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;人的ミスのリスク&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #991b1b;&quot;&gt;高（疲労や急ぎの作業で、必要なコードを誤って消去してしまう事故が発生）。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;極小（一度検証された正しい解決手順が100%正確に再現される）。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;複数ブランチでの流用&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;他の派生ブランチで同じマージを行う際、別の開発者が再度同じ悩みを抱える。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;同一リポジトリ内であれば、別のブランチのリベースでも自動適用可能。&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- セクション③: git rerere 動作の3ステップ --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】git rerere 動作の3ステップ（記録・検知・自動適用）&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;git rerere&lt;/code&gt; がどのようにして競合を記憶し、自動解決を適用するのか、その3ステップの動作フローを確認しましょう。
    &lt;/p&gt;

    &lt;!-- 図解② --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/16RBsiwZYcF5fPJKgTmwtGLEx7e_qxaaw&quot; alt=&quot;git rerere 動作の3ステップ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】①衝突検知・事前状態の自動記録 → ②初回のみ人間が手動解決してコミット → ③次回以降、同一競合をGitが全自動で0秒適用&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;ステップ①【競合検知・事前状態の自動記録】&lt;/h3&gt;
    &lt;p&gt;
        &lt;code&gt;git merge&lt;/code&gt; や &lt;code&gt;git rebase&lt;/code&gt; でコンフリクトが発生した瞬間、Gitはターミナルに以下のようなメッセージを出力します：
    &lt;/p&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;$ git merge main
Auto-merging Services/OrderService.cs
CONFLICT (content): Merge conflict in Services/OrderService.cs
Recorded preimage for &#39;Services/OrderService.cs&#39;
Automatic merge failed; fix conflicts and then commit the result.&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;
        ここで表示された &lt;code&gt;Recorded preimage for &#39;Services/OrderService.cs&#39;&lt;/code&gt; という行に注目してください！&lt;br/&gt;
        これが「コンフリクト前の衝突形状（Preimage）をGitがキャッシュに記録した」合図です。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;ステップ②【初回のみ人間が手動解決してコミット】&lt;/h3&gt;
    &lt;p&gt;
        初回の1回だけは、開発者が通常通りエディタ（VS CodeやVisual Studio）で競合マーカー（&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt; / &lt;code&gt;=======&lt;/code&gt; / &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;）を解消します。&lt;br/&gt;
        解消後、ファイルをステージングしてコミット（または &lt;code&gt;git rebase --continue&lt;/code&gt;）します。
    &lt;/p&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;$ git add Services/OrderService.cs
$ git commit -m &quot;Merge main and resolve conflict in OrderService&quot;
Recorded resolution for &#39;Services/OrderService.cs&#39;.&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;
        コミット時に &lt;code&gt;Recorded resolution for &#39;Services/OrderService.cs&#39;.&lt;/code&gt; と表示され、Gitは「この競合パターンに対して、人間がどのように解決したか（Postimage）」を学習・保存しました！
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;ステップ③【次回以降、同一競合をGitが全自動適用】&lt;/h3&gt;
    &lt;p&gt;
        将来、別のブランチのテストマージを破棄してやり直した際や、トピックブランチのリベース中に再び同じコミットが衝突した際、Gitは以下のように応答します：
    &lt;/p&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;$ git rebase main
Auto-merging Services/OrderService.cs
CONFLICT (content): Merge conflict in Services/OrderService.cs
Resolved &#39;Services/OrderService.cs&#39; using previous resolution.&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;
        なんと！&lt;code&gt;Resolved &#39;Services/OrderService.cs&#39; using previous resolution.&lt;/code&gt; と表示され、&lt;strong&gt;前回の解決策が自動適用されてファイルが既に綺麗に解決済みの状態&lt;/strong&gt;になっています！&lt;br/&gt;
        開発者はエディタで競合を手直しする必要すらなく、そのまま &lt;code&gt;git add&lt;/code&gt; して次へ進むことができます。
    &lt;/p&gt;

    &lt;!-- セクション④: rerereの有効化とキャッシュの仕組み --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【図解】rerereの有効化とキャッシュ（.git/rr-cache）の仕組み&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;git rerere&lt;/code&gt; は標準のGitに最初から組み込まれていますが、デフォルトでは無効（オフ）になっています。まずは一発で有効化しましょう。
    &lt;/p&gt;

    &lt;!-- 図解③ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1IdNmLP78BcR0kCP_zD77OKOUDMM1svDM&quot; alt=&quot;rerereの有効化とキャッシュの仕組み&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】git config --global rerere.enabled true で一発有効化！ .git/rr-cache/ に衝突パターンと解決策が自動学習・蓄積される内部構造&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;rerere をグローバルに有効化するコマンド&lt;/h3&gt;
    &lt;p&gt;
        開発マシンのターミナル（PowerShell等）で以下のコマンドを実行するだけで、全リポジトリで自動記録が有効化されます。
    &lt;/p&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;# 全リポジトリで rerere を有効化（推奨）
$ git config --global rerere.enabled true

# （オプション）自動解決されたファイルを自動で git add まで行わせる場合
$ git config --global rerere.autoupdate true&lt;/code&gt;&lt;/pre&gt;

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #3b82f6; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #1d4ed8; font-size: 16px;&quot;&gt;💡 rerere.autoupdate の挙動&lt;/strong&gt;
        &lt;p style=&quot;margin: 6px 0 0 0; line-height: 1.8;&quot;&gt;
            &lt;code&gt;rerere.autoupdate true&lt;/code&gt; を設定すると、Gitが過去の解決結果を適用したファイルを自動的にステージング（&lt;code&gt;git add&lt;/code&gt;）してくれます。&lt;br/&gt;
            初心者のうちは「自動解決された結果を目視で確認してからステージングしたい」ことが多いため、まずは &lt;code&gt;rerere.enabled true&lt;/code&gt; だけを設定するのが安全でおすすめです。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;内部構造: .git/rr-cache ディレクトリ&lt;/h3&gt;
    &lt;p&gt;
        Gitは衝突の差分ブロックからSHA-1ハッシュ（フィンガープリント）を計算し、&lt;code&gt;.git/rr-cache/&amp;lt;ハッシュ&amp;gt;/&lt;/code&gt; ディレクトリ内に以下の2つのファイルを保持します：
    &lt;/p&gt;
    &lt;ul style=&quot;line-height: 1.85;&quot;&gt;
        &lt;li&gt;&lt;code&gt;preimage&lt;/code&gt;: 競合発生時の両ブランチの差分テキスト（衝突パターン）&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;postimage&lt;/code&gt;: 人間が手動で正しく解決したあとの完成形テキスト&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;
        不要になった古いキャッシュは、&lt;code&gt;git rerere gc&lt;/code&gt; コマンドで安全に定期クリーンアップ（デフォルトで未解決は15日、解決済みは60日）されるため、リポジトリが肥大化する心配もありません。
    &lt;/p&gt;

    &lt;!-- セクション⑤: C#現場での git rerere 実践術 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【図解】C#現場での git rerere 実践術&lt;/h2&gt;
    &lt;p&gt;
        実際の.NET / C# 開発現場で、&lt;code&gt;git rerere&lt;/code&gt; がどれほどの威力を発揮するのか、頻出シナリオを見ていきましょう。
    &lt;/p&gt;

    &lt;!-- 図解④ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1jVA_2mk0Sjs_UKsEahPIb5QcxBoXUdJS&quot; alt=&quot;C#現場での git rerere 実践術&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】長期間フィーチャーブランチやNuGet定義（.csproj）、共通ヘッダー更新での頻出コンフリクトを自動解消して開発を爆速化&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;シナリオ①: 長期フィーチャー開発での「使い捨てテストマージ」&lt;/h3&gt;
    &lt;p&gt;
        機能開発に数週間かかる場合、「現時点で &lt;code&gt;main&lt;/code&gt; とマージしたら動くかどうか確認したい」という理由で、ローカルで一時的に &lt;code&gt;main&lt;/code&gt; をマージして動作確認（ビルド・単体テスト）することがあります。&lt;br/&gt;
        動作確認が終わったら、履歴を汚さないために &lt;code&gt;git reset --hard HEAD~1&lt;/code&gt; でマージを取り消します。&lt;br/&gt;
        もし &lt;code&gt;rerere&lt;/code&gt; が無ければ、後日本当にプルリクエストをマージする際に、また同じコンフリクトを一から手動解決しなければなりません。&lt;br/&gt;
        しかし &lt;code&gt;git rerere&lt;/code&gt; が有効なら、&lt;strong&gt;テストマージ時に解いた解決策がしっかり記憶されているため、本番マージの際は一瞬で自動解決&lt;/strong&gt;されます！
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;シナリオ②: .csproj（NuGetパッケージ更新）での頻発コンフリクト&lt;/h3&gt;
    &lt;p&gt;
        C#プロジェクトファイル（&lt;code&gt;.csproj&lt;/code&gt;）は、複数人が同時にパッケージを追加・バージョンアップした際にコンフリクトが起きやすい典型例です。
    &lt;/p&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;&amp;lt;!-- 衝突例: MyApp.csproj --&amp;gt;
&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
    &amp;lt;PackageReference Include=&quot;Microsoft.EntityFrameworkCore&quot; Version=&quot;9.0.2&quot; /&amp;gt;
    &amp;lt;PackageReference Include=&quot;Serilog.AspNetCore&quot; Version=&quot;8.0.3&quot; /&amp;gt;
=======
    &amp;lt;PackageReference Include=&quot;Microsoft.EntityFrameworkCore&quot; Version=&quot;9.0.2&quot; /&amp;gt;
    &amp;lt;PackageReference Include=&quot;FluentValidation.AspNetCore&quot; Version=&quot;11.3.0&quot; /&amp;gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; main&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;
        両方のパッケージを綺麗に統合した結果を一度コミットしておけば、フィーチャーブランチ側で何度リベースをやり直しても、.csprojの競合で立ち止まることは二度となくなります！
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #10b981; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #047857; font-size: 17px;&quot;&gt;🛡️ C#エンジニアのための安全確認コマンド&lt;/strong&gt;
        &lt;p style=&quot;margin: 6px 0 0 0; line-height: 1.8;&quot;&gt;
            自動解決された内容が意図通りか確認したい場合は、コミット前に &lt;code&gt;git diff&lt;/code&gt; を叩くだけです：&lt;br/&gt;
            &lt;code&gt;$ git diff&lt;/code&gt;&lt;br/&gt;
            また、&lt;code&gt;git rerere status&lt;/code&gt; で現在どのファイルが自動解決対象として処理されたか一覧表示できます。もし手違いで誤った解決を記録してしまった場合は、&lt;code&gt;git rerere clear&lt;/code&gt; や &lt;code&gt;git rerere forget &amp;lt;file&amp;gt;&lt;/code&gt; で安全にキャッシュを忘却させることが可能です！
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑥: 本日のまとめ＆次回予告 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ まとめ＆次回予告&lt;/h2&gt;
    
    &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 22px 24px; margin: 30px 0; border: 1px solid #cbd5e1;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; font-size: 19px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;font-size: 24px; margin-right: 10px;&quot;&gt;📌&lt;/span&gt; 本日の最重要ポイントまとめ
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 12px 0 0 0; padding-left: 22px; line-height: 1.9; font-size: 16px;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;git rerere は「コンフリクト解決の自動再生機」:&lt;/strong&gt; Reuse Recorded Resolutionの略で、一度解いた衝突パターンをGitが学習・自動適用！&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;有効化は1コマンド:&lt;/strong&gt; &lt;code&gt;git config --global rerere.enabled true&lt;/code&gt; を打つだけで今すぐ全リポジトリで稼働開始。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;動作の3ステップ:&lt;/strong&gt; ①衝突時に &lt;code&gt;Recorded preimage&lt;/code&gt; → ②初回手動コミットで &lt;code&gt;Recorded resolution&lt;/code&gt; → ③次回以降 &lt;code&gt;Resolved using previous resolution&lt;/code&gt; で0秒自動解決。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;テストマージとリベースの強力な味方:&lt;/strong&gt; 破棄前提の事前結合テストや日々のリベースで、同じ競合を何度も解く苦痛をゼロ化。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;誤解決も安全に取り消し可能:&lt;/strong&gt; &lt;code&gt;git rerere forget &amp;lt;file&amp;gt;&lt;/code&gt; で特定のキャッシュを消去して再学習させられる安心設計。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background: #eff6ff; border: 2px dashed #3b82f6; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #1d4ed8; margin-top: 0; font-size: 18px;&quot;&gt;🚀 次回予告【Day 32】&lt;/h3&gt;
        &lt;p style=&quot;margin: 6px 0 0 0; font-size: 16px; line-height: 1.8;&quot;&gt;
            次回は、ターミナルでの日々のGit操作スピードを爆発的に高める効率化テクニック——&lt;br/&gt;
            &lt;strong&gt;【git switch - やエイリアス設定で日常操作を10倍爆速化する】&lt;/strong&gt;をお届けします！&lt;br/&gt;
            直前のブランチへ一瞬で戻る &lt;code&gt;switch -&lt;/code&gt; の使い方や、タイピング数を半減させるプロ厳選の &lt;code&gt;git config alias&lt;/code&gt;、PowerShellでのGitブランチ可視化（posh-git）まで、エンジニアの手元を異次元に加速させる時短テクニックを大公開します。お楽しみに！
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/3351522459389581503/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-31git-rerere.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3351522459389581503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3351522459389581503'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-31git-rerere.html' title='【Day 31】git rerere で過去に解決したコンフリクトを全自動解決させる魔法'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1Ct0xLvaPRtfaZvXiwXdHELAmACYeLHFL=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-5550363542946473238</id><published>2026-10-29T09:21:09.150+09:00</published><updated>2026-10-29T09:21:09.150+09:00</updated><title type='text'>【Day 33】コンテナ名で名前解決するサービスディスカバリ（DNS） 〜変動するIPアドレスの完全撲滅・Docker内蔵DNS（127.0.0.11）の仕組み・Composeサービス名通信・ネットワークエイリアス・C# HttpClient/EF Core現場実践〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1ivbuSyGeMU1QodJ5f1wwxktKUh1fCckW&quot; alt=&quot;Day 33 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 33: コンテナ名で名前解決するサービスディスカバリ（DNS）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 導入メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: linear-gradient(135deg, #e0f2fe 0%, #f0fdf4 100%); border-left: 6px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0; box-shadow: 0 4px 12px rgba(13,183,237,0.08);&quot;&gt;
        &lt;div style=&quot;font-size: 32px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;font-size: 15.5px; color: #0f172a;&quot;&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; font-weight: bold; color: #0369a1; font-size: 17px;&quot;&gt;「コンテナを再起動するたびにIPアドレスが変わってしまう… 接続先IPを毎回書き換えるなんて無理では？」&lt;/p&gt;
            &lt;p style=&quot;margin: 0; line-height: 1.8;&quot;&gt;
                前回（Day 32）は、Dockerネットワークの全体像と3大ドライバー（Bridge / Host / None）、そしてユーザー定義ブリッジによる隔離について学びました。&lt;br/&gt;
                そこで30年来のベテランエンジニアが必ず抱くのが&lt;strong&gt;「IPアドレスの変動」に関する切実な不安&lt;/strong&gt;です。&lt;br/&gt;
                &lt;em&gt;「物理サーバーやオンプレミスVMなら、サーバーに固定プライベートIP（例: 192.168.1.10）を割り当て、C#の接続文字列や設定ファイルに書き込んでいた。だが、Dockerコンテナは起動・破棄のたびに `172.20.0.2` や `172.20.0.5` などIPがコロコロ変わる。hostsファイルを手作業で書き換えるのか？ どうやってWeb APIからDBを見失わずに接続し続けられるのか？」&lt;/em&gt;&lt;br/&gt;
                その答えこそが、Dockerが標準提供する&lt;strong&gt;「組み込みDNSサーバー（Embedded DNS Server: 127.0.0.11）」によるサービスディスカバリ（名前解決）&lt;/strong&gt;です！&lt;br/&gt;
                本講義では、動的IPの苦悩を完全消滅させるDNSの仕組みから、Composeでの通信手法、そしてC# (.NET) 現場で致命的な障害を生む「DNSキャッシュ問題（TTL）」の完全回避策まで徹底解説します！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 目次 --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 10px; padding: 22px 26px; margin: 32px 0;&quot;&gt;
        &lt;h3 style=&quot;margin-top: 0; margin-bottom: 14px; font-size: 18px; color: #0f172a; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 6px; padding: 2px 8px; font-size: 13px; margin-right: 10px; font-weight: bold;&quot;&gt;INDEX&lt;/span&gt;
            本日の講義メニュー
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 22px; color: #334155; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;第1章: なぜIPアドレス直接指定は破綻するのか？ 〜hostsファイル管理の限界とDockerの動的IP〜&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第2章: Docker内蔵DNSサーバー（127.0.0.11）の驚くべき仕組み&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第3章: Docker Composeにおけるサービス名通信とネットワークエイリアス（aliases）&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第4章: C# (.NET) 現場での実践：HttpClientと接続文字列のサービスディスカバリ設計&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第5章: 現場必須のDNS疎通確認コマンド（nslookup, ping, curl）とトラブルシューティング&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第6章: 第7部核心！理解度チェッククイズ（全3問・詳細解説付き）&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;次回予告: 【Day 34】ポートマッピング（-p 8080:80）とポート競合の解決法&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第1章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;1&lt;/span&gt;
        なぜIPアドレス直接指定は破綻するのか？ 〜hostsファイル管理の限界とDockerの動的IP〜
    &lt;/h2&gt;

    &lt;p&gt;
        オンプレミスの物理サーバーや固定VMの時代、システム構築時の定石は「固定プライベートIPアドレス（Static IP）の払い出し」でした。&lt;br/&gt;
        開発サーバー `192.168.10.21`、検証DB `192.168.10.55`、本番API `10.0.2.100` といったIPアドレスを表計算ソフト（Excel）のIP台帳に几帳面に記録し、各サーバーの `C:\Windows\System32\drivers\etc\hosts` や `/etc/hosts` に手動で書き込んで名前解決していた現場も少なくありません。
    &lt;/p&gt;

    &lt;div style=&quot;background: #fff1f2; border-left: 5px solid #f43f5e; padding: 16px 20px; border-radius: 6px; margin: 24px 0;&quot;&gt;
        &lt;strong style=&quot;color: #9f1239; font-size: 16px;&quot;&gt;⚠️ 旧来の「固定IP＋hosts手動管理」が抱えていた3大悲劇&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; color: #881337; font-size: 15px; line-height: 1.75;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;変更コストと伝搬漏れ:&lt;/strong&gt; DBサーバーのリプレイスでIPが1つ変わるだけで、接続元の全Webサーバー・バッチサーバーのhostsを手作業で書き換えて回る必要があった。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Gitリポジトリとの不協和音:&lt;/strong&gt; 接続文字列に生IPアドレスを書いてしまうと、開発機（192.168.x.x）とステージング（10.0.x.x）でコードや設定を共有できず、コミット事故の温床になった。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;コンテナの動的ライフサイクルとの完全な不一致:&lt;/strong&gt; コンテナは「使い捨て（Ephemeral）」が基本思想です。障害発生時やスケールアウト時に数秒で再起動されますが、そのたびに全く異なる空きIPが割り当てられるため、固定IP前提の設計は即死します。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        Dockerコンテナの世界では、「IPアドレスに依存した設計」は完全にアンチパターンです。&lt;br/&gt;
        コンテナが破棄されて再生成されても、割り当てIPが `172.20.0.2` から `172.20.0.6` にシフトしても、呼び出し側は&lt;strong&gt;「サービス名（例: `api` や `sqlserver`）」という普遍の名前だけを指定して通信できなければなりません&lt;/strong&gt;。&lt;br/&gt;
        この「サービス名から現在の生きたIPアドレスを動的に引き当てる仕組み」を、クラウドネイティブの世界では&lt;strong&gt;サービスディスカバリ（Service Discovery）&lt;/strong&gt;と呼びます。
    &lt;/p&gt;

    &lt;!-- 図解①配置 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1SXD1AvVBbJ-Flg14q2MO2HsEmtLx-U3W&quot; alt=&quot;hosts手動管理 vs Docker内蔵DNS&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】旧来のhosts手動更新地獄 vs 現代のDocker組み込みDNS自動解決&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        上の図解が示すとおり、手動管理のhostsファイルとIP台帳の苦しみから開発者を救い出すのが、Dockerが自動で提供する「内蔵DNSによるサービスディスカバリ」です。&lt;br/&gt;
        開発者はもう、サーバーのIPアドレスを調べる必要も、メモに残す必要もありません。
    &lt;/p&gt;

    &lt;!-- 第2章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;2&lt;/span&gt;
        Docker内蔵DNSサーバー（127.0.0.11）の驚くべき仕組み
    &lt;/h2&gt;

    &lt;p&gt;
        「でも、Docker内部でどうやって名前解決しているの？ 特別なDNSソフトウェア（BINDやdnsmasqなど）をインストールしているの？」と疑問に思うかもしれません。&lt;br/&gt;
        実は、Dockerには&lt;strong&gt;LinuxカーネルとDockerデーモンが協調して動作する軽量な「組み込みDNSサーバー（Embedded DNS）」&lt;/strong&gt;が標準で備わっています。
    &lt;/p&gt;

    &lt;p&gt;
        ユーザー定義ブリッジ（User-defined Bridge）に参加しているコンテナの内部に入り、`/etc/resolv.conf` を確認してみると、非常に興味深いIPアドレスが設定されていることが分かります：
    &lt;/p&gt;

    &lt;!-- コードブロック: resolv.conf --&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 20px 24px; font-family: &#39;Consolas&#39;, &#39;Monaco&#39;, monospace; font-size: 14px; overflow-x: auto; margin: 24px 0; line-height: 1.7; box-shadow: 0 4px 14px rgba(0,0,0,0.2);&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;# コンテナ内部のDNS設定を確認する&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;$&lt;/span&gt; cat /etc/resolv.conf

&lt;span style=&quot;color: #64748b;&quot;&gt;# 出力結果:&lt;/span&gt;
nameserver &lt;span style=&quot;color: #a7f3d0; font-weight: bold;&quot;&gt;127.0.0.11&lt;/span&gt;
options ndots:0
    &lt;/div&gt;

    &lt;p&gt;
        この &lt;code&gt;127.0.0.11&lt;/code&gt; こそが、Docker組み込みDNSのリッスンアドレスです。&lt;br/&gt;
        コンテナ内のあらゆるネットワークリクエスト（C#の `HttpClient`、EF CoreのDB接続、`curl`、`ping` など）がホスト名を解決しようとすると、OSは自動的にこの `127.0.0.11` にDNSクエリ（ポート53）を送信します。
    &lt;/p&gt;

    &lt;!-- 図解②配置 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/18ToP8xJX6pTFuwv81LsgMQerSUwLHNr7&quot; alt=&quot;Docker内蔵DNSの解決フロー&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】127.0.0.11がコンテナ名から最新IPを即時解決する3ステップルーティング&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;background: #f0fdf4; border-left: 5px solid #10b981; padding: 18px 22px; border-radius: 6px; margin: 26px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #065f46; font-size: 16.5px;&quot;&gt;💡 Docker内蔵DNS（127.0.0.11）の名前解決3ステップ&lt;/h4&gt;
        &lt;ol style=&quot;margin: 0; padding-left: 20px; color: #047857; font-size: 15px; line-height: 1.8;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;ステップ① コンテナ内からの名前解決要求:&lt;/strong&gt; C#アプリが `http://api/weather` を呼び出すと、OSはDNSサーバー `127.0.0.11` に「`api` のIPアドレスを教えて」と問い合わせます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;ステップ② Docker内部ルーティングテーブルの照会:&lt;/strong&gt; `127.0.0.11` はDockerデーモンと直結しており、同じネットワーク内にいるコンテナ名・Composeサービス名・エイリアス一覧を保持しています。該当するコンテナの「現在の内部IP（例: `172.20.0.3`）」を即座に回答します。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;ステップ③ 外部インターネットへのフォワード:&lt;/strong&gt; もし問い合わせ先がコンテナ名ではなく外部ドメイン（例: `nuget.org` や `google.com`）だった場合、内蔵DNSはホストマシンの外部DNS（社内DNSや8.8.8.8等）へ透過的にリクエストを中継（Forward）します。&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;p&gt;
        この洗練された仕組みのおかげで、コンテナが再起動してIPアドレスがどれだけ変わろうとも、Dockerデーモンが内部テーブルを数ミリ秒で更新するため、アプリ側は一切の設定変更なしに通信を継続できるのです。
    &lt;/p&gt;

    &lt;!-- 第3章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;3&lt;/span&gt;
        Docker Composeにおけるサービス名通信とネットワークエイリアス（aliases）
    &lt;/h2&gt;

    &lt;p&gt;
        実際の開発現場において、このサービスディスカバリの恩恵を最大限に受けるのが&lt;strong&gt;Docker Compose&lt;/strong&gt;です。&lt;br/&gt;
        Docker Composeを使うと、同一ファイル内に記述されたサービス群は&lt;strong&gt;自動的に専用のユーザー定義ブリッジネットワークを作成し、サービス名がそのままホスト名（DNS名）として登録&lt;/strong&gt;されます。
    &lt;/p&gt;

    &lt;!-- コードブロック: docker-compose.yml --&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 20px 24px; font-family: &#39;Consolas&#39;, &#39;Monaco&#39;, monospace; font-size: 14px; overflow-x: auto; margin: 24px 0; line-height: 1.7; box-shadow: 0 4px 14px rgba(0,0,0,0.2);&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;# docker-compose.yml: サービス名通信とエイリアス設定の実例&lt;/span&gt;
&lt;span style=&quot;color: #f43f5e;&quot;&gt;services:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;web-front:&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;build: ./FrontendApp&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;ports:&lt;/span&gt;
      - &lt;span style=&quot;color: #a7f3d0;&quot;&gt;&quot;8080:80&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;environment:&lt;/span&gt;
      &lt;span style=&quot;color: #64748b;&quot;&gt;# サービス名「order-api」で直接HTTP通信できる！&lt;/span&gt;
      - &lt;span style=&quot;color: #fed7aa;&quot;&gt;OrderApiUrl=http://order-api:8080&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;networks:&lt;/span&gt;
      - &lt;span style=&quot;color: #a7f3d0;&quot;&gt;backend-net&lt;/span&gt;

  &lt;span style=&quot;color: #38bdf8;&quot;&gt;order-api:&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;build: ./OrderApi&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;environment:&lt;/span&gt;
      &lt;span style=&quot;color: #64748b;&quot;&gt;# サービス名「sqlserver」で直接接続！&lt;/span&gt;
      - &lt;span style=&quot;color: #fed7aa;&quot;&gt;ConnectionStrings__Default=Server=sqlserver,1433;Database=OrderDb;User Id=sa;Password=P@ssw0rd123;TrustServerCertificate=True&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;networks:&lt;/span&gt;
      &lt;span style=&quot;color: #38bdf8;&quot;&gt;backend-net:&lt;/span&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# ネットワークエイリアス（別名）の付与！&lt;/span&gt;
        &lt;span style=&quot;color: #cbd5e1;&quot;&gt;aliases:&lt;/span&gt;
          - &lt;span style=&quot;color: #a7f3d0;&quot;&gt;api.internal.local&lt;/span&gt;
          - &lt;span style=&quot;color: #a7f3d0;&quot;&gt;legacy-order-service&lt;/span&gt;

  &lt;span style=&quot;color: #38bdf8;&quot;&gt;sqlserver:&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;image: mcr.microsoft.com/mssql/server:2022-latest&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;environment:&lt;/span&gt;
      - &lt;span style=&quot;color: #fed7aa;&quot;&gt;ACCEPT_EULA=Y&lt;/span&gt;
      - &lt;span style=&quot;color: #fed7aa;&quot;&gt;MSSQL_SA_PASSWORD=P@ssw0rd123&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;networks:&lt;/span&gt;
      - &lt;span style=&quot;color: #a7f3d0;&quot;&gt;backend-net&lt;/span&gt;

&lt;span style=&quot;color: #f43f5e;&quot;&gt;networks:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;backend-net:&lt;/span&gt;
    &lt;span style=&quot;color: #cbd5e1;&quot;&gt;driver: bridge&lt;/span&gt;
    &lt;/div&gt;

    &lt;!-- 図解③配置 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/10qtU_gC71aKWWODWkXq8YCQvKqBH04_q&quot; alt=&quot;Composeサービス名とネットワークエイリアス&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】Composeサービス名による直接通信と複数別名（aliases）の柔軟な活用&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #3b82f6; padding: 18px 22px; border-radius: 6px; margin: 26px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #1e40af; font-size: 16.5px;&quot;&gt;🌟 ネットワークエイリアス（aliases）の強力な使い所&lt;/h4&gt;
        &lt;p style=&quot;margin: 0 0 10px 0; color: #1e3a8a; font-size: 15px; line-height: 1.75;&quot;&gt;
            Composeのサービス名だけでなく、`networks.&lt;ネットワーク名&gt;.aliases` を指定することで、コンテナに&lt;strong&gt;複数の別名（FQDNや短縮名）&lt;/strong&gt;を付与できます。
        &lt;/p&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #1e3a8a; font-size: 14.5px; line-height: 1.75;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;レガシーシステムの移行:&lt;/strong&gt; 旧環境のコードにハードコードされていたドメイン（例: `api.internal.local`）をエイリアスに設定することで、C#コードを1行も修正せずにコンテナ環境へ移行できる。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;本番FQDNのモック化:&lt;/strong&gt; 本番で利用する外部SaaSドメインをローカルのモックコンテナのエイリアスにしておくことで、本番と同一の設定値でローカル結合テストを行える。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第4章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;4&lt;/span&gt;
        C# (.NET) 現場での実践：HttpClientと接続文字列のサービスディスカバリ設計
    &lt;/h2&gt;

    &lt;p&gt;
        それでは、C# (.NET 8 / .NET 9) のコードでこのサービスディスカバリを安全に扱う実装方法を見ていきましょう。&lt;br/&gt;
        ASP.NET Core Web APIやコンソールアプリでコンテナ名を利用する際、&lt;strong&gt;絶対に避けては通れない「.NETのDNSキャッシュ問題（TTL）」&lt;/strong&gt;があります。
    &lt;/p&gt;

    &lt;div style=&quot;background: #fffbeb; border-left: 5px solid #f59e0b; padding: 18px 22px; border-radius: 6px; margin: 26px 0;&quot;&gt;
        &lt;strong style=&quot;color: #b45309; font-size: 16px;&quot;&gt;⚠️ C#エンジニアが本番でハマる「古いIPの掴みっぱなし現象」&lt;/strong&gt;
        &lt;p style=&quot;margin: 8px 0 0 0; color: #92400e; font-size: 15px; line-height: 1.75;&quot;&gt;
            単に `new HttpClient()` をシングルトンで使い回すと、初回名前解決時のIPアドレス（ソケット接続）を無限にキャッシュし続けます。&lt;br/&gt;
            その結果、相手の `order-api` コンテナがデプロイや障害で再起動して新IPになった瞬間、&lt;strong&gt;「相手は正常稼働しているのに、自アプリからは HttpRequestException (SocketException: Connection refused) が出続ける」&lt;/strong&gt;という怪奇現象が発生します。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;p&gt;
        この問題をエレガントに解決するのが、ASP.NET Coreの標準機能である &lt;code&gt;IHttpClientFactory&lt;/code&gt; と &lt;code&gt;PooledConnectionLifetime&lt;/code&gt; の設定です。
    &lt;/p&gt;

    &lt;!-- コードブロック: C# Program.cs --&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 20px 24px; font-family: &#39;Consolas&#39;, &#39;Monaco&#39;, monospace; font-size: 14px; overflow-x: auto; margin: 24px 0; line-height: 1.7; box-shadow: 0 4px 14px rgba(0,0,0,0.2);&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;// Program.cs: C# (.NET 8) での安全なサービス名HttpClient登録&lt;/span&gt;
&lt;span style=&quot;color: #c084fc;&quot;&gt;var&lt;/span&gt; builder = WebApplication.CreateBuilder(args);

&lt;span style=&quot;color: #64748b;&quot;&gt;// 1. 環境変数または appsettings.json からサービスURLを取得（デフォルトはサービス名指定）&lt;/span&gt;
&lt;span style=&quot;color: #c084fc;&quot;&gt;string&lt;/span&gt; orderApiBase = builder.Configuration[&lt;span style=&quot;color: #a7f3d0;&quot;&gt;&quot;OrderApiUrl&quot;&lt;/span&gt;] ?? &lt;span style=&quot;color: #a7f3d0;&quot;&gt;&quot;http://order-api:8080&quot;&lt;/span&gt;;

&lt;span style=&quot;color: #64748b;&quot;&gt;// 2. IHttpClientFactory と SocketsHttpHandler によるDNS定期再解決の設定&lt;/span&gt;
builder.Services.AddHttpClient(&lt;span style=&quot;color: #a7f3d0;&quot;&gt;&quot;OrderApiClient&quot;&lt;/span&gt;, client =&gt;
{
    client.BaseAddress = &lt;span style=&quot;color: #c084fc;&quot;&gt;new&lt;/span&gt; Uri(orderApiBase);
    client.DefaultRequestHeaders.Add(&lt;span style=&quot;color: #a7f3d0;&quot;&gt;&quot;Accept&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a7f3d0;&quot;&gt;&quot;application/json&quot;&lt;/span&gt;);
    client.Timeout = TimeSpan.FromSeconds(10);
})
.ConfigurePrimaryHttpMessageHandler(() =&gt; &lt;span style=&quot;color: #c084fc;&quot;&gt;new&lt;/span&gt; SocketsHttpHandler
{
    &lt;span style=&quot;color: #64748b;&quot;&gt;// ★最重要: 接続プールの有効期限を2分に設定！&lt;/span&gt;
    &lt;span style=&quot;color: #64748b;&quot;&gt;// コンテナ再起動でIPアドレスが更新されても、最長2分でDNSを再解決して新IPへ自動追従する&lt;/span&gt;
    PooledConnectionLifetime = TimeSpan.FromMinutes(2)
});

&lt;span style=&quot;color: #64748b;&quot;&gt;// 3. EF Core DBコンテキストの登録（接続文字列にコンテナ名を指定）&lt;/span&gt;
&lt;span style=&quot;color: #c084fc;&quot;&gt;string&lt;/span&gt; dbConn = builder.Configuration.GetConnectionString(&lt;span style=&quot;color: #a7f3d0;&quot;&gt;&quot;Default&quot;&lt;/span&gt;)
    ?? &lt;span style=&quot;color: #a7f3d0;&quot;&gt;&quot;Server=sqlserver,1433;Database=OrderDb;User Id=sa;Password=P@ssw0rd123;TrustServerCertificate=True&quot;&lt;/span&gt;;

builder.Services.AddDbContext&amp;lt;OrderDbContext&amp;gt;(options =&gt;
    options.UseSqlServer(dbConn));

&lt;span style=&quot;color: #c084fc;&quot;&gt;var&lt;/span&gt; app = builder.Build();
    &lt;/div&gt;

    &lt;!-- 図解④配置 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1NKDLqVKQkj8MD8MDpDhSwO0mTP-fFLNC&quot; alt=&quot;C#現場のサービスディスカバリ実践設計&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】.NET HttpClient/EF Coreでのサービス名接続とDNSキャッシュ（TTL）対策&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        上の図解のとおり、&lt;code&gt;PooledConnectionLifetime&lt;/code&gt; を短時間（例: 1〜5分）に設定しておくことで、コンテナ環境特有の「動的IPアドレス切り替え」に完全対応できます。&lt;br/&gt;
        EF CoreなどのADO.NET系プロバイダ（Microsoft.Data.SqlClient）も、内部の接続プールが切断を検知すると自動的に再接続時にDNS解決を行うため、サービス名指定（`Server=sqlserver`）で安全に運用できます。
    &lt;/p&gt;

    &lt;!-- 第5章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;5&lt;/span&gt;
        現場必須のDNS疎通確認コマンド（nslookup, ping, curl）とトラブルシューティング
    &lt;/h2&gt;

    &lt;p&gt;
        コンテナ同士が「名前で繋がらない！」というトラブルに直面したとき、ホストマシンからいくらpingを打っても問題は切り分けられません。&lt;br/&gt;
        &lt;strong&gt;「コンテナの内部に入って、127.0.0.11のDNS応答と疎通をテストする」&lt;/strong&gt;のがプロの鉄則です。
    &lt;/p&gt;

    &lt;!-- コードブロック: CLI確認 --&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 20px 24px; font-family: &#39;Consolas&#39;, &#39;Monaco&#39;, monospace; font-size: 14px; overflow-x: auto; margin: 24px 0; line-height: 1.7; box-shadow: 0 4px 14px rgba(0,0,0,0.2);&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;# 1. コンテナ内から特定のサービス名のIP解決を直接テスト（nslookup）&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker exec -it web-front nslookup order-api&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 正常時の出力例:&lt;/span&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;Server:    127.0.0.11&lt;/span&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;Address:   127.0.0.11#53&lt;/span&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;Name:      order-api&lt;/span&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;Address:   172.20.0.3&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 2. curl によるHTTP疎通テスト（ヘッダーとステータス確認）&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker exec -it web-front curl -I http://order-api:8080/health&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 3. Alpine等の軽量コンテナで ping による低レイヤー疎通確認&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker exec -it web-front ping -c 3 order-api&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 4. ネットワークに参加している全コンテナの名前とIPを一括調査&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker network inspect backend-net --format &#39;{{json .Containers}}&#39; | jq .&lt;/span&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #fffbeb; border-left: 5px solid #f59e0b; padding: 18px 22px; border-radius: 6px; margin: 28px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #b45309; font-size: 16.5px;&quot;&gt;🛠️ トラブルシューティング：「サービス名が名前解決できない！」ときの3大チェック&lt;/h4&gt;
        &lt;ol style=&quot;margin: 0; padding-left: 20px; color: #92400e; font-size: 14.5px; line-height: 1.8;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;同一のカスタムネットワークに所属しているか？&lt;/strong&gt;&lt;br/&gt;
                異なる Compose ファイルや別々のネットワークに所属しているコンテナ同士は、名前解決テーブルが隔離されています。`docker network inspect` で双方が同じネットワーク内に存在するか確認してください。
            &lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;デフォルトブリッジ（docker0）を使っていないか？&lt;/strong&gt;&lt;br/&gt;
                `docker run` を単体で実行してネットワークを指定しなかった場合、デフォルトブリッジとなり組み込みDNSが無効化されます。`--network &lt;ネットワーク名&gt;` を必ず指定しましょう。
            &lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;アンダースコア（_）を含むホスト名になっていないか？&lt;/strong&gt;&lt;br/&gt;
                RFC規約上、DNSホスト名にアンダースコア（_）が含まれると一部のHTTPクライアントやライブラリ（.NETやJava等）で名前解決に失敗する場合があります。Composeのサービス名にはハイフン（`-`）を使用するのがベストプラクティスです。
            &lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;!-- 第6章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;6&lt;/span&gt;
        第7部核心！理解度チェッククイズ
    &lt;/h2&gt;

    &lt;p&gt;本日の重要ポイントを3問のクイズでおさらいしましょう！ 各枠をクリックすると正解と解説が展開します。&lt;/p&gt;

    &lt;!-- クイズ1 --&gt;
    &lt;details style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 16px 20px; margin: 18px 0; cursor: pointer;&quot;&gt;
        &lt;summary style=&quot;font-weight: bold; color: #0f172a; font-size: 16px;&quot;&gt;
            Q1: Dockerのユーザー定義ネットワークにおいて、コンテナ内の `/etc/resolv.conf` に設定されている組み込みDNSサーバーのIPアドレスはどれでしょうか？
        &lt;/summary&gt;
        &lt;div style=&quot;margin-top: 14px; padding-top: 14px; border-top: 1px dashed #cbd5e1; color: #334155; font-size: 15px; line-height: 1.8;&quot;&gt;
            &lt;p&gt;&lt;strong style=&quot;color: #2563eb;&quot;&gt;正解: 127.0.0.11&lt;/strong&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;【解説】:&lt;/strong&gt; Dockerはコンテナ専用のループバックアドレス空間にある `127.0.0.11` で内蔵DNSサーバーを起動します。コンテナからの名前解決要求はこのアドレスに送られ、Dockerデーモンが管理する内部テーブルから相手コンテナの最新IPアドレスが即座に返却されます。&lt;/p&gt;
        &lt;/div&gt;
    &lt;/details&gt;

    &lt;!-- クイズ2 --&gt;
    &lt;details style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 16px 20px; margin: 18px 0; cursor: pointer;&quot;&gt;
        &lt;summary style=&quot;font-weight: bold; color: #0f172a; font-size: 16px;&quot;&gt;
            Q2: Docker Compose環境で、C# Web APIからSQL Serverコンテナへ接続する際の接続文字列として最も推奨される指定方法はどれでしょうか？
        &lt;/summary&gt;
        &lt;div style=&quot;margin-top: 14px; padding-top: 14px; border-top: 1px dashed #cbd5e1; color: #334155; font-size: 15px; line-height: 1.8;&quot;&gt;
            &lt;p&gt;&lt;strong style=&quot;color: #2563eb;&quot;&gt;正解: Server=sqlserver,1433;Database=OrderDb;...（Composeサービス名を直接指定する）&lt;/strong&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;【解説】:&lt;/strong&gt; 動的に変化するIPアドレス（例: 172.20.0.4）やホスト側のIP（localhost等）を直接ハードコードしてはいけません。Composeで定義したサービス名（`sqlserver`）を指定することで、Docker内蔵DNSが常に最新のIPアドレスを自動解決し、環境差分やコンテナ再起動にも耐えられる堅牢な構成になります。&lt;/p&gt;
        &lt;/div&gt;
    &lt;/details&gt;

    &lt;!-- クイズ3 --&gt;
    &lt;details style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 16px 20px; margin: 18px 0; cursor: pointer;&quot;&gt;
        &lt;summary style=&quot;font-weight: bold; color: #0f172a; font-size: 16px;&quot;&gt;
            Q3: C# (.NET) アプリケーションでコンテナ名を使ったHTTP通信を行う際、「コンテナ再起動によるIP変更に追従できなくなる問題（DNSキャッシュ問題）」を回避するための正しい設定はどれでしょうか？
        &lt;/summary&gt;
        &lt;div style=&quot;margin-top: 14px; padding-top: 14px; border-top: 1px dashed #cbd5e1; color: #334155; font-size: 15px; line-height: 1.8;&quot;&gt;
            &lt;p&gt;&lt;strong style=&quot;color: #2563eb;&quot;&gt;正解: IHttpClientFactory を利用し、SocketsHttpHandler の PooledConnectionLifetime を適切な時間（数分程度）に設定する。&lt;/strong&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;【解説】:&lt;/strong&gt; .NETの標準的なHttpClientは一度接続したソケットのDNS結果を保持し続ける傾向があります。`SocketsHttpHandler.PooledConnectionLifetime`（接続プールの生存期間）を数分（例: 2分）に制限することで、定期的に接続を再オープンし、Docker内蔵DNSに対して最新のIPアドレスを再問い合わせさせることができます。&lt;/p&gt;
        &lt;/div&gt;
    &lt;/details&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); color: #f8fafc; border-radius: 10px; padding: 26px 30px; margin: 45px 0; box-shadow: 0 6px 18px rgba(15,23,42,0.3);&quot;&gt;
        &lt;h3 style=&quot;margin-top: 0; color: #38bdf8; font-size: 20px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;font-size: 24px; margin-right: 10px;&quot;&gt;🚀&lt;/span&gt;
            次回予告：【Day 34】ポートマッピング（-p 8080:80）とポート競合の解決法
        &lt;/h3&gt;
        &lt;p style=&quot;margin: 0; line-height: 1.8; color: #cbd5e1; font-size: 15.5px;&quot;&gt;
            次回は、コンテナ間ネットワークと並ぶ最重要テーマ&lt;strong&gt;「ホストとコンテナのポート境界線（ポートフォワーディング）」&lt;/strong&gt;を徹底解剖します！&lt;br/&gt;
            「&lt;code&gt;-p 8080:80&lt;/code&gt; と書いたとき、ホストOSとコンテナの間でパケットはどう流れているのか？」「ホストのIISやSQL Serverとポートが衝突したときの回避法は？」「環境変数を使ってポート番号を柔軟に外出しする方法とは？」&lt;br/&gt;
            現場で誰もが一度は頭を抱えるポートトラブルを完全克服します。次回もお楽しみに！
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/5550363542946473238/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-33dns-ipdockerdns1270011composec.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/5550363542946473238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/5550363542946473238'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-33dns-ipdockerdns1270011composec.html' title='【Day 33】コンテナ名で名前解決するサービスディスカバリ（DNS） 〜変動するIPアドレスの完全撲滅・Docker内蔵DNS（127.0.0.11）の仕組み・Composeサービス名通信・ネットワークエイリアス・C# HttpClient/EF Core現場実践〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1ivbuSyGeMU1QodJ5f1wwxktKUh1fCckW=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-5970391838225293027</id><published>2026-10-28T18:12:42.938+09:00</published><updated>2026-10-28T18:12:42.938+09:00</updated><title type='text'>【Day 30】git log -S（つるはし検索）で消えた過去の関数・定数を発掘する</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1v5qXy7CJQqpkXx1B4UYHYDN0BR82ijdj&quot; alt=&quot;Day 30 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 30】git log -S（つるはし検索）で消えた過去の関数・定数を発掘する&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 29では、コードの犯人や導入理由を特定する&lt;strong&gt;「git blame &amp; git log -L」&lt;/strong&gt;によるコード考古学の基礎を学びました。&lt;br/&gt;
            そして本日のDay 30は、長期運用や保守開発の現場でエンジニアが必ず一度は直面する大ピンチ——&lt;br/&gt;
            &lt;strong&gt;「昔確かに存在したはずのあのC#メソッドや定数、いつ誰が消した！？」&lt;/strong&gt;&lt;br/&gt;
            という謎を、全リポジトリのコミット差分から瞬時に一発発掘する極意——&lt;br/&gt;
            &lt;strong&gt;【git log -S（つるはし検索）で消えた過去の関数・定数を発掘する】&lt;/strong&gt;をお届けします！&lt;br/&gt;
            「仕様変更で半年前に削除したロジックが、法改正や方針転換で急遽また必要になった」「過去のテスト済み定数の値を確認したいが、現行コードのどこにも見当たらない……」&lt;br/&gt;
            そんな時、何千件もあるコミットログを手作業で1件ずつめくって探していませんか？&lt;br/&gt;
            Gitが誇る&lt;strong&gt;「Pickaxe（つるはし）検索」&lt;/strong&gt;を使いこなせば、指定したテキストの「出現回数の増減（新設・削除）」を全履歴から瞬時にバイナリスキャン！&lt;br/&gt;
            わずか0.1秒で目的のコミットを掘り当て、当時の完全なコードをピンポイントで安全にサルベージ（復元）できます！&lt;br/&gt;
            開発現場での無駄な再車輪開発を防ぎ、生産性を劇的に高めるプロの技を完全マスターしましょう！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        ソフトウェア開発が数年続くと、不要と判断されたコードや古いインターフェースはリファクタリングで削除されていきます。&lt;br/&gt;
        しかし現実のビジネスでは、「一度廃止された仕様が、別の顧客向けに再必要になった」「過去の複雑な計算ロジックを参考にして新機能を設計したい」という状況が日常茶飯事です。&lt;br/&gt;
        現行コードのどこを検索しても存在しないコードを、Gitの全歴史の地層から一瞬で掘り出す最強のツールが &lt;code&gt;git log -S&lt;/code&gt; です。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;SVN全ログ手動検索とGit Pickaxe検索の仕組みの違いと圧倒的優位性を理解する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git log -S&lt;/code&gt;（つるはし検索）で消えた関数・定数の誕生・削除コミットを一発特定する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git log -S&lt;/code&gt;（出現回数増減）と &lt;code&gt;git log -G&lt;/code&gt;（正規表現差分検索）の決定的な違いと使い分けを完全習得する&lt;/li&gt;
            &lt;li&gt;特定したコミットから &lt;code&gt;git show&lt;/code&gt; コマンドで当時のコードをピンポイントにサルベージ（安全復元）する手順を体得する&lt;/li&gt;
            &lt;li&gt;C#実戦シナリオを通じて、発掘した過去ロジックを最新のC# 12構文にリファクタリングして安全に再統合するフローを確立する&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: SVN全ログ手動検索 vs Git Pickaxe検索 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】SVN全ログ手動検索 vs Git Pickaxe検索の決定的違い&lt;/h2&gt;
    &lt;p&gt;
        Subversion (SVN) でも過去のコミット履歴を検索することは可能でしたが、消えたコードを探す作業は過酷を極めました。
    &lt;/p&gt;

    &lt;!-- 図解① --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1YHW9BeL1QiAp2GEnWVolHfKU_3gZPOC1&quot; alt=&quot;SVN全ログ手動検索 vs Git Pickaxe検索の比較&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】中央サーバー通信と目視検索で重いSVN vs ローカル差分の文字列増減を0.1秒で即座に検出するGit Pickaxe検索&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        SVNとGitにおける過去コード探査の体験差は、以下の3点に集約されます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15.5px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #f1f5f9; border-bottom: 2px solid #cbd5e1;&quot;&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 22%;&quot;&gt;比較項目&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 38%; color: #991b1b;&quot;&gt;SVN 全ログ検索&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 40%; color: #1e40af;&quot;&gt;Git Pickaxe検索 (git log -S)&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;探査スピード&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;中央サーバー通信必須。巨大なログの取得・検索に数分〜数十分を要する。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;ローカル完全完結。数万コミットのリポジトリでも0.1秒で即時検出。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;検索対象&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;コミットメッセージの文字列一致のみ。差分テキストの中身までは追えない。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;全コミットの差分本文をスキャン。「その文字列の出現回数が増減した瞬間」を検知。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;ノイズの排除&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;不可。コミットメッセージにメソッド名が書かれていなければ完全に空振り。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;完全排除。コード内にその文字が生まれたコミットと消えたコミットだけを厳密抽出。&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- セクション③: git log -S による消えたコード発掘の3ステップ --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】git log -S による消えたコード発掘の3ステップ&lt;/h2&gt;
    &lt;p&gt;
        それでは、実際に消えたC#コードを発掘して安全に復元する3ステップの黄金フローを解説します。
    &lt;/p&gt;

    &lt;!-- 図解② --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1JtnOgipZ6Ptu7h4Rq01cvKw4je3Spwvj&quot; alt=&quot;git log -S による消えたコード発掘の3ステップ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】①検索実行（git log -S）→ ②履歴確認（削除理由とPR特定）→ ③安全復元（git show）の完全フロー&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;ステップ①【検索実行】git log -S で出現・削除コミットを一撃抽出&lt;/h3&gt;
    &lt;p&gt;
        ターミナルを開き、探したい関数名や定数名を指定して &lt;code&gt;git log -S&lt;/code&gt; を実行します。このとき、必ず &lt;code&gt;-p&lt;/code&gt;（パッチ表示）または &lt;code&gt;--oneline&lt;/code&gt; を付与するのがプロの鉄則です。
    &lt;/p&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;# 構文: git log -S &quot;探したい文字列&quot; -p
$ git log -S &quot;CalculateLegacyTax&quot; -p -- Services/TaxService.cs

commit d7a8b92c4f1e0a8b92c4f1e0a8b92c4f1e0a8b92
Author: Suzuki Ichiro &amp;lt;suzuki@example.com&amp;gt;
Date:   Wed Apr 16 11:20:15 2025 +0900

    Refactor: 旧税率計算ロジックの廃止と新API統合 (#345)

diff --git a/Services/TaxService.cs b/Services/TaxService.cs
--- a/Services/TaxService.cs
+++ b/Services/TaxService.cs
@@ -45,18 +45,0 @@ public class TaxService
-    public decimal CalculateLegacyTax(decimal price, DateTime targetDate)
-    {
-        // 2024年以前の旧税率計算ロジック
-        if (targetDate &amp;lt; TaxConstants.TransitionDate)
-        {
-            return price * 0.08m;
-        }
-        return price * 0.10m;
-    }&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;
        ご覧ください！コミット &lt;code&gt;d7a8b92c&lt;/code&gt; で、&lt;code&gt;-&lt;/code&gt;（削除記号）と共に対象のメソッドが消去された瞬間が完全に記録されています！
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;ステップ②【履歴確認】なぜ削除されたのかの背景・PR番号を特定&lt;/h3&gt;
    &lt;p&gt;
        コードが消えた瞬間が特定できたら、絶対にやってはいけないのが「何も考えずにすぐコードを復活させること」です。&lt;br/&gt;
        コミットメッセージ &lt;code&gt;Refactor: 旧税率計算ロジックの廃止と新API統合 (#345)&lt;/code&gt; に注目してください。&lt;br/&gt;
        GitHub上でプルリクエスト &lt;strong&gt;#345&lt;/strong&gt; を開き、当時のレビュアーの議論や仕様書のリンクを確認します。&lt;br/&gt;
        「なぜ削除されたのか？」「仕様上の欠陥があったのか？それとも単に当時の画面で不要になっただけなのか？」を理解して初めて、安全な再利用への道が開かれます。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;ステップ③【安全復元】git show で当時のコードをピンポイント取得&lt;/h3&gt;
    &lt;p&gt;
        当時の正常動作していたコードを取り出すには、&lt;code&gt;git show&lt;/code&gt; コマンドに対象コミットの「直前（チルダ &lt;code&gt;~1&lt;/code&gt; または キャレット &lt;code&gt;^&lt;/code&gt;）」を指定します。
    &lt;/p&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;# 削除コミットの1つ前（生きていた最後の姿）を表示・確認
$ git show d7a8b92c~1:Services/TaxService.cs

# 必要であればファイル全体ではなく該当メソッドだけを安全に別名保存
$ git show d7a8b92c~1:Services/TaxService.cs &amp;gt; TaxService_Old.cs&lt;/code&gt;&lt;/pre&gt;

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #3b82f6; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #1d4ed8; font-size: 16px;&quot;&gt;💡 一歩進んだプロの技: git restore でファイルごとサルベージ&lt;/strong&gt;
        &lt;p style=&quot;margin: 6px 0 0 0; line-height: 1.8;&quot;&gt;
            もし完全に削除されて消滅してしまったファイル（例: &lt;code&gt;Services/LegacyTaxCalculator.cs&lt;/code&gt;）そのものを丸ごと作業ツリーに復活させたい場合は、最新の &lt;code&gt;git restore&lt;/code&gt; コマンドが最も安全です：&lt;br/&gt;
            &lt;code&gt;$ git restore --source=d7a8b92c~1 -- Services/LegacyTaxCalculator.cs&lt;/code&gt;&lt;br/&gt;
            歴史を壊すことなく、安全に作業ツリーに未ステージングの状態で過去ファイルを取り出せます！
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- セクション④: git log -S vs git log -G の使い分け --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【図解】git log -S vs git log -G の使い分け（Pickaxe vs Regex）&lt;/h2&gt;
    &lt;p&gt;
        Gitには、差分を検索するオプションとして &lt;code&gt;-S&lt;/code&gt;（Pickaxe）のほかに &lt;strong&gt;&lt;code&gt;-G&lt;/code&gt;（Regex）&lt;/strong&gt; が存在します。この2つの違いを正しく理解しているかどうかが、初級者とプロの分水嶺です。
    &lt;/p&gt;

    &lt;!-- 図解③ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1VS5xvvkix6-1NC5w3MoYeKaO0Pjtvd2z&quot; alt=&quot;git log -S vs git log -G の使い分け&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】出現回数の増減を厳密抽出する-S（新設・削除特定）vs 差分行の正規表現一致を網羅する-G（影響範囲全追跡）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15.5px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #f1f5f9; border-bottom: 2px solid #cbd5e1;&quot;&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 22%;&quot;&gt;比較項目&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 38%; color: #1e40af;&quot;&gt;git log -S &quot;文字列&quot;（Pickaxe）&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 40%; color: #7c3aed;&quot;&gt;git log -G &quot;正規表現&quot;（Regex Diff）&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;検出の判定基準&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;ファイル全体で、その文字列の&lt;strong&gt;「出現回数（個数）」が増減したか&lt;/strong&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;コミットの&lt;strong&gt;差分行（+ または -）&lt;/strong&gt;に正規表現パターンが含まれているか&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;行移動・インデント変更&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;【無視】出現回数が変わらないためノイズとして除外される&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #991b1b;&quot;&gt;【検出】差分行に対象文字列があるためすべてヒットしてしまう&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;引数や実装の変更&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;【無視】関数名自体の個数が変わらなければヒットしない&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;【検出】関数のシグネチャ変更や呼び出し箇所修正を全網羅&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;最適なユースケース&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;「いつ追加されたか」「いつ誰が削除したか」を一発で特定したい時&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;「この関数が関与したすべての変更・呼び出し元の修正履歴」を網羅したい時&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;# 【-S】消えた定数や関数の誕生・削除コミットだけをピンポイント検索
$ git log -S &quot;MAX_RETRY_COUNT&quot; --oneline

# 【-G】TaxServiceクラスのCalculateで始まる全メソッドの変更差分を網羅検索
$ git log -G &quot;public .* Calculate.*Tax&quot; -p -- Services/&lt;/code&gt;&lt;/pre&gt;

    &lt;!-- セクション⑤: C#現場でのコードサルベージ実践術 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【図解】C#現場でのコードサルベージ実践術&lt;/h2&gt;
    &lt;p&gt;
        過去のコードを無事に掘り当てたら、最後は現行システムへの&lt;strong&gt;「安全な再統合（リファクタリング）」&lt;/strong&gt;です。
    &lt;/p&gt;

    &lt;!-- 図解④ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1rud41jRRM2qWSwqkZ6ouba8QHr3By2xF&quot; alt=&quot;C#現場でのコードサルベージ実践術&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】過去に廃止された旧ロジックを発掘し、最新C# 12の構文に合わせて安全にリファクタリング・再統合&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;レガシーコード復活の3大チェックリスト&lt;/h3&gt;
    &lt;p&gt;
        1〜2年前に書かれたC#コードを現代のシステムに復活させる際は、以下の3点を必ず確認して近代化（Modernize）しましょう。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #10b981; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #047857; font-size: 17px;&quot;&gt;🛡️ 過去コード安全復活のチェックリスト&lt;/strong&gt;
        &lt;ol style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;同期メソッドの非同期化（async/await）:&lt;/strong&gt;&lt;br/&gt;
                過去の同期ブロッキングなI/O呼び出しやDBアクセスを、現行の &lt;code&gt;ValueTask&amp;lt;T&amp;gt;&lt;/code&gt; や &lt;code&gt;CancellationToken&lt;/code&gt; 対応に書き換える。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;最新のC#言語機能の適用:&lt;/strong&gt;&lt;br/&gt;
                冗長な &lt;code&gt;if/else&lt;/code&gt; の連続を、C#の強力な&lt;strong&gt;パターンマッチング（switch式）&lt;/strong&gt;にリファクタリングして可読性を向上させる。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;単体テスト（xUnit / NUnit）の同時発掘:&lt;/strong&gt;&lt;br/&gt;
                プロダクションコードだけでなく、&lt;code&gt;git log -S &quot;CalculateLegacyTax&quot; -- Tests/&lt;/code&gt; で当時の単体テストも同時にサルベージし、仕様の正しさを自動テストで保証する。&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;!-- C# 現代化サンプル --&gt;
    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;// 【発掘した過去コード（旧C#構文）】
public decimal CalculateLegacyTax(decimal price, DateTime targetDate)
{
    if (targetDate &amp;lt; TaxConstants.TransitionDate)
    {
        return price * 0.08m;
    }
    return price * 0.10m;
}

// 【C# 12仕様にリファクタリング・近代化した新コード】
public decimal CalculateModernTax(decimal price, DateOnly targetDate) =&amp;gt; targetDate switch
{
    var d when d &amp;lt; TaxConstants.TransitionDateOnly =&amp;gt; price * 0.08m,
    _ =&amp;gt; price * 0.10m
};&lt;/code&gt;&lt;/pre&gt;

    &lt;!-- セクション⑥: 本日のまとめ＆次回予告 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ まとめ＆次回予告&lt;/h2&gt;
    
    &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 22px 24px; margin: 30px 0; border: 1px solid #cbd5e1;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; font-size: 19px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;font-size: 24px; margin-right: 10px;&quot;&gt;📌&lt;/span&gt; 本日の最重要ポイントまとめ
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 12px 0 0 0; padding-left: 22px; line-height: 1.9; font-size: 16px;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;消えたコードは git log -S で探せ:&lt;/strong&gt; 全コミット差分から指定文字列の出現回数が増減した瞬間だけを0.1秒でピンポイント抽出！&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;-S と -G の使い分け:&lt;/strong&gt; 関数の誕生・削除を特定するなら &lt;code&gt;-S&lt;/code&gt;（Pickaxe）、引数変更や影響範囲を全件追跡するなら &lt;code&gt;-G&lt;/code&gt;（Regex Diff）。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;削除理由の背景確認を怠るな:&lt;/strong&gt; コミットメッセージとPR番号から、なぜ当時削除されたのかを必ず確認して仕様不整合を防止。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;git show で安全にサルベージ:&lt;/strong&gt; &lt;code&gt;git show &amp;lt;hash^&amp;gt;:FilePath&lt;/code&gt; で削除直前の完全なコードを抽出。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;最新C#への近代化:&lt;/strong&gt; 発掘した過去資産をそのまま貼り付けるのではなく、最新の構文や非同期設計にアップデートして再活用。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background: #eff6ff; border: 2px dashed #3b82f6; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #1d4ed8; margin-top: 0; font-size: 18px;&quot;&gt;🚀 次回予告【Day 31】&lt;/h3&gt;
        &lt;p style=&quot;margin: 6px 0 0 0; font-size: 16px; line-height: 1.8;&quot;&gt;
            次回は、同じブランチの統合で何度も何度も同じコンフリクトを解消させられて疲弊しているエンジニアに贈る奇跡の機能——&lt;br/&gt;
            &lt;strong&gt;【git rerere で過去に解決したコンフリクトを全自動解決させる魔法】&lt;/strong&gt;をお届けします！&lt;br/&gt;
            「Reuse Recorded Resolution（記録された解決の再利用）」を有効化するだけで、Gitが過去のコンフリクト解消手順を自動学習し、二度と同じ衝突で手を動かす必要がなくなります。お楽しみに！
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/5970391838225293027/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-30git-log-s.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/5970391838225293027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/5970391838225293027'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-30git-log-s.html' title='【Day 30】git log -S（つるはし検索）で消えた過去の関数・定数を発掘する'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1v5qXy7CJQqpkXx1B4UYHYDN0BR82ijdj=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-8477220137955428868</id><published>2026-10-28T09:21:15.729+09:00</published><updated>2026-10-28T09:21:15.729+09:00</updated><title type='text'>【Day 32】Dockerネットワークの仕組み（Bridge, Host, None） 〜仮想ブリッジによる通信分離・デフォルトブリッジの罠・組み込みDNS・C# Web APIとDBの多層防御設計〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1wCFIZNg1H9FgTPS4mKbpc62hfT2EdS-Q&quot; alt=&quot;Day 32 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 32: Dockerネットワークの仕組み（Bridge, Host, None）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 導入メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: linear-gradient(135deg, #e0f2fe 0%, #f0fdf4 100%); border-left: 6px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0; box-shadow: 0 4px 12px rgba(13,183,237,0.08);&quot;&gt;
        &lt;div style=&quot;font-size: 32px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;font-size: 15.5px; color: #0f172a;&quot;&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; font-weight: bold; color: #0369a1; font-size: 17px;&quot;&gt;「コンテナ同士はどうやって通信している？ 外部にDBを晒さずにWeb APIとだけ安全に繋ぐには？」&lt;/p&gt;
            &lt;p style=&quot;margin: 0; line-height: 1.8;&quot;&gt;
                前回（Day 31）までで第6部『データの永続化とボリューム』が完結し、新メンバーが参加した初日にコマンド一発でDBと初期シードデータが完全復元される「ゼロセットアップ環境」の構築手法を学びました。&lt;br/&gt;
                そして今日から、いよいよ本講座の最重要タームの1つである&lt;strong&gt;新章『第7部: コンテナ間ネットワークとポート管理』&lt;/strong&gt;が開幕します！&lt;br/&gt;
                物理サーバーやオンプレミスインフラを30年経験してきたエンジニアの皆様は、こう疑問に思われるかもしれません：&lt;br/&gt;
                &lt;em&gt;「物理サーバーならL2スイッチにLANケーブルを挿し、VLANを設定すれば通信を分離できた。Hyper-Vなら仮想スイッチを作って仮想NICを割り当てていた。では、Dockerコンテナ同士は一体どうやって通信しているのか？ なぜIPアドレスではなくコンテナ名でpingが通るのか？ 外部インターネットからデータベースを完全に隠蔽するにはどう設計すべきか？」&lt;/em&gt;&lt;br/&gt;
                本講義では、Dockerが裏側で構築する仮想ネットワークブリッジの正体から、3大ネットワークドライバー（Bridge / Host / None）の使い分け、初心者が必ずハマる「デフォルトブリッジの罠」、そしてC# Web APIとSQL Serverを組み合わせたセキュアな多層防御ネットワーク設計まで、完全網羅で解説します！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 目次 --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 10px; padding: 22px 26px; margin: 32px 0;&quot;&gt;
        &lt;h3 style=&quot;margin-top: 0; margin-bottom: 14px; font-size: 18px; color: #0f172a; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 6px; padding: 2px 8px; font-size: 13px; margin-right: 10px; font-weight: bold;&quot;&gt;INDEX&lt;/span&gt;
            本日の講義メニュー
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 22px; color: #334155; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;第1章: 物理スイッチ・VLANから「ソフトウェア定義ネットワーク（SDN）」へのパラダイムシフト&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第2章: Dockerの3大ネットワークドライバー（Bridge, Host, None）徹底比較&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第3章: デフォルトブリッジ（docker0）の罠と「ユーザー定義ブリッジ」の決定的な違い&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第4章: C# Web API ＋ SQL Server のセキュアな多層防御ネットワーク設計&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第5章: 現場必須の docker network CLIコマンド＆トラブルシューティング&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第6章: 理解度チェッククイズ（全3問・詳細解説付き）&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;次回予告: 【Day 33】コンテナ間通信とポートマッピング（-p / EXPOSE）の真実&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第1章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;1&lt;/span&gt;
        物理スイッチ・VLANから「ソフトウェア定義ネットワーク（SDN）」へのパラダイムシフト
    &lt;/h2&gt;

    &lt;p&gt;
        物理サーバー時代、サーバー間のネットワークを構築・分離する作業は「肉体労働と社内調整の連続」でした。&lt;br/&gt;
        ラックマウントサーバーの裏に潜り込んでCAT6 LANケーブルを敷設し、フロアのL2/L3スイッチに接続。さらにWebサーバー用VLAN（DMZ）とDBサーバー用VLAN（内部セグメント）を分離するために、ネットワーク専門チームに申請書を提出して承認を待つ…というプロセスに、数日から数週間を要することも珍しくありませんでした。
    &lt;/p&gt;

    &lt;div style=&quot;background: #fff1f2; border-left: 5px solid #f43f5e; padding: 16px 20px; border-radius: 6px; margin: 24px 0;&quot;&gt;
        &lt;strong style=&quot;color: #9f1239; font-size: 16px;&quot;&gt;⚠️ 物理・従来仮想化（Hyper-V/VMware）ネットワークの課題&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; color: #881337; font-size: 15px; line-height: 1.75;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;配線と機器の物理的制約:&lt;/strong&gt; ポート数やケーブル配線の物理限界があり、構成変更に大きな手間とコストが発生。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;手動設定によるヒューマンエラー:&lt;/strong&gt; Hyper-V仮想スイッチやポートVLANの設定ミスによるパケット漏洩や通信遮断事故。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;開発環境での再現困難:&lt;/strong&gt; 本番同様の多層ネットワーク（Web/API/DB）を開発用ノートPC上で手軽に再現することが不可能だった。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        Dockerは、このネットワーク構築の常識を根底から覆しました。&lt;br/&gt;
        Linuxカーネルの&lt;strong&gt;「ネットワーク名前空間（Network Namespace）」&lt;/strong&gt;と&lt;strong&gt;「仮想イーサネットペア（veth: Virtual Ethernet pair）」&lt;/strong&gt;という仕組みを活用し、ホストOSの内部にソフトウェアだけで仮想スイッチ（仮想ブリッジ）を瞬時に作り出す&lt;strong&gt;ソフトウェア定義ネットワーク（SDN: Software-Defined Networking）&lt;/strong&gt;を実現したのです。
    &lt;/p&gt;

    &lt;!-- 図解①配置 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1RSD1NfxaC6eGG5GfPqTg4pUUouf8D-4y&quot; alt=&quot;物理スイッチ・VLAN vs Dockerネットワーク&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】旧来の物理スイッチ・VLAN配線 vs 現代のソフトウェア定義ネットワーク（SDN）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        Dockerネットワークの世界では、物理LANケーブルは「vethペアと呼ばれる仮想ケーブル」に、物理L2スイッチは「カーネル内の仮想ブリッジ」に置き換わります。&lt;br/&gt;
        コンテナが起動すると、仮想ケーブルの一端がコンテナ内部の `eth0` となり、もう一端がホスト側の仮想スイッチに自動的にプラグインされます。&lt;br/&gt;
        これにより、開発者は物理インフラチームの手を借りることなく、&lt;strong&gt;わずか1行のコマンドや `docker-compose.yml` の宣言だけで、本番と寸分違わぬ安全な隔離ネットワークを自分のPC上に構築できる&lt;/strong&gt;ようになったのです。
    &lt;/p&gt;

    &lt;!-- 第2章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;2&lt;/span&gt;
        Dockerの3大ネットワークドライバー（Bridge, Host, None）徹底比較
    &lt;/h2&gt;

    &lt;p&gt;
        Dockerには、コンテナの接続形態に応じて複数の&lt;strong&gt;「ネットワークドライバー（Network Drivers）」&lt;/strong&gt;が用意されています。&lt;br/&gt;
        その中でも、日常の開発から本番運用において絶対に把握しておくべき基本ドライバーが以下の3つです：
    &lt;/p&gt;

    &lt;!-- 図解②配置 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/11vnNxTV8bIUpiNgiVk2uE34zed4Jvd2m&quot; alt=&quot;3大ネットワークドライバーの比較&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】Dockerの主要ネットワークドライバー（Bridge・Host・None）の特徴と使い分け&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;margin: 28px 0; overflow-x: auto;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15px; text-align: left; background: #ffffff; box-shadow: 0 2px 8px rgba(0,0,0,0.06); border-radius: 8px; overflow: hidden;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #0f172a; color: #ffffff;&quot;&gt;
                    &lt;th style=&quot;padding: 14px 16px; border: 1px solid #334155;&quot;&gt;ドライバー名&lt;/th&gt;
                    &lt;th style=&quot;padding: 14px 16px; border: 1px solid #334155;&quot;&gt;通信の仕組み&lt;/th&gt;
                    &lt;th style=&quot;padding: 14px 16px; border: 1px solid #334155;&quot;&gt;メリット&lt;/th&gt;
                    &lt;th style=&quot;padding: 14px 16px; border: 1px solid #334155;&quot;&gt;注意点・デメリット&lt;/th&gt;
                    &lt;th style=&quot;padding: 14px 16px; border: 1px solid #334155;&quot;&gt;主な用途&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0; font-weight: bold; color: #0284c7;&quot;&gt;bridge（標準）&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;ホスト内にプライベート仮想ブリッジを作成し、NAT経由で外部と通信&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;完全な名前空間分離、安全なポート転送（-p）、コンテナ間DNS連携&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;パケット転送（NAT/iptables）によるごく僅かなオーバーヘッド&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;Web API、データベース、キャッシュなど&lt;strong&gt;全体の95%以上&lt;/strong&gt;&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0; font-weight: bold; color: #ea580c;&quot;&gt;host（ホスト直結）&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;コンテナがホストのネットワーク名前空間を直接共有&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;NATなし、オーバーヘッドゼロ、超低遅延・超高スループット&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;ホストのポートと直接衝突（80番の二重利用不可）、Linuxネイティブのみ&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;高速ログ収集エージェント、IoT・リアルタイム通信、超大規模トラフィック&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0; font-weight: bold; color: #16a34a;&quot;&gt;none（完全隔離）&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;ループバック（127.0.0.1）のみ。外部・他コンテナとの接続一切遮断&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;外部攻撃や情報漏洩リスクが100%排除された鉄壁のセキュリティ&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;ネットワーク通信が一切行えない&lt;/td&gt;
                    &lt;td style=&quot;padding: 14px 16px; border: 1px solid #e2e8f0;&quot;&gt;機密データの暗号化・署名バッチ、オフライン機械学習、セキュリティ検証&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #f0fdf4; border-left: 5px solid #22c55e; padding: 18px 22px; border-radius: 6px; margin: 28px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 8px 0; color: #15803d; font-size: 16.5px;&quot;&gt;💡 実務での選び方ガイドライン&lt;/h4&gt;
        &lt;p style=&quot;margin: 0; font-size: 15px; color: #166534; line-height: 1.8;&quot;&gt;
            実務のWebアプリケーション（ASP.NET Core、SQL Server、Redis等）開発においては、&lt;strong&gt;「99%のケースで bridge ドライバー（特に後述するユーザー定義ブリッジ）を採用する」&lt;/strong&gt;がベストプラクティスです。&lt;br/&gt;
            `host` は「どうしてもマイクロ秒単位のレイテンシを削りたい特殊なミドルウェア」でのみ検討し、`none` は「ネットワークを完全に遮断したい機密バッチ」でのみ使用します。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第3章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;3&lt;/span&gt;
        デフォルトブリッジ（docker0）の罠と「ユーザー定義ブリッジ」の決定的な違い
    &lt;/h2&gt;

    &lt;p&gt;
        Dockerをインストールした直後、デフォルトで `bridge` という名前のネットワーク（内部名: `docker0`）が最初から存在しています。&lt;br/&gt;
        初心者が `docker run -d --name webapi ...` のようにネットワークを指定せずにコンテナを起動すると、自動的にこの「デフォルトブリッジ」に接続されます。&lt;br/&gt;
        &lt;strong&gt;しかし、ここに重大な落とし穴が存在します！ 実務現場でデフォルトブリッジをそのまま使っては絶対にダメな2大理由があります。&lt;/strong&gt;
    &lt;/p&gt;

    &lt;!-- 図解③配置 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1dJDbU5wmkAzTP6rfS-nVypVxs0uhQqC7&quot; alt=&quot;デフォルトブリッジ vs ユーザー定義ブリッジ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】デフォルトブリッジ（docker0）の危険な罠 vs ユーザー定義ブリッジの組み込みDNS&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;border-left: 4px solid #ea580c; padding-left: 12px; margin-top: 30px; color: #9a3412; font-size: 18.5px;&quot;&gt;
        罠①: コンテナ名による自動名前解決（組み込みDNS）が無効化されている！
    &lt;/h3&gt;
    &lt;p&gt;
        デフォルトブリッジ上では、Dockerの組み込みDNSサーバーが動作しません。&lt;br/&gt;
        つまり、Web APIコンテナからデータベースコンテナへ接続しようとして `Server=sql-db;` と指定しても、&lt;strong&gt;「ホストが見つかりません（Name or service not known）」というDNSエラーで即死&lt;/strong&gt;します。&lt;br/&gt;
        接続するためには動的に割り振られたIPアドレス（例: `172.17.0.3`）を直打ちしなければなりませんが、コンテナを再起動したり再作成するたびにIPアドレスは変動するため、実質的にシステム運用が破綻します。
    &lt;/p&gt;

    &lt;h3 style=&quot;border-left: 4px solid #ea580c; padding-left: 12px; margin-top: 30px; color: #9a3412; font-size: 18.5px;&quot;&gt;
        罠②: すべてのコンテナが無条件で同居し、セキュリティ境界が消失する！
    &lt;/h3&gt;
    &lt;p&gt;
        ネットワークを指定せずに起動したすべてのコンテナは、同じ `docker0` 仮想ブリッジに無条件で同居します。&lt;br/&gt;
        これは「社内の全部署のPCと基幹DBを同じハブに無造作に挿している」のと同じ状態であり、開発用の実験コンテナや脆弱性のあるコンテナから、重要データベースへのパケット盗聴や不正アクセスが可能になってしまいます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #eff6ff; border: 2px solid #3b82f6; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #1e40af; font-size: 17px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;font-size: 20px; margin-right: 8px;&quot;&gt;✨&lt;/span&gt;
            ユーザー定義ブリッジ（User-defined Bridge）の絶大なメリット
        &lt;/h4&gt;
        &lt;p style=&quot;margin: 0 0 12px 0; color: #1e3a8a; font-size: 15px; line-height: 1.8;&quot;&gt;
            `docker network create my-net` で明示的に作成した「ユーザー定義ブリッジ」にコンテナを参加させると、Dockerの&lt;strong&gt;組み込みDNSサーバー（IP: 127.0.0.11）&lt;/strong&gt;が自動的に稼働します！
        &lt;/p&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #1e3a8a; font-size: 14.5px; line-height: 1.75;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;コンテナ名による自動名前解決:&lt;/strong&gt; `http://webapi:8080` や `Server=sql-db,1433` と指定するだけで、IPが変わっても自動追従！&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;堅牢なネットワーク分離:&lt;/strong&gt; 異なるユーザー定義ブリッジに属するコンテナ同士は互いに一切通信できず、安全な境界線を確立。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;動的な接続・切断:&lt;/strong&gt; 稼働中のコンテナを停止させることなく、`docker network connect` コマンドで後からネットワークに追加可能。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第4章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;4&lt;/span&gt;
        C# Web API ＋ SQL Server のセキュアな多層防御ネットワーク設計
    &lt;/h2&gt;

    &lt;p&gt;
        それでは、C#/.NETの開発現場において最も一般的かつ強固な&lt;strong&gt;「Web API ＋ SQL Server の多層防御ネットワーク」&lt;/strong&gt;を実際に設計してみましょう！&lt;br/&gt;
        現場で最も多く見られるセキュリティ事故は、&lt;strong&gt;「ローカル開発でSSMSから確認したいから」という安易な理由で、本番の `docker-compose.yml` にも DB の `ports: - &quot;1433:1433&quot;` を書いたままデプロイしてしまうケース&lt;/strong&gt;です。
    &lt;/p&gt;

    &lt;!-- 図解④配置 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/12tfOGyAS0M6fX9ATISF0jD39aVaEBgEX&quot; alt=&quot;C#現場の多層防御ネットワーク設計&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】C#現場での多層防御：Web APIは公開・SQL Serverは内部秘匿の安全設計&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;border-left: 4px solid #512bd4; padding-left: 12px; margin-top: 30px; color: #512bd4; font-size: 18.5px;&quot;&gt;
        鉄壁の2層分離 docker-compose.yml サンプル
    &lt;/h3&gt;
    &lt;p&gt;
        以下の Compose 定義では、外部公開用ネットワーク（`frontend-net`）と内部専用ネットワーク（`backend-net`）の2つを定義し、Web APIをその「架け橋（プロキシ）」として配置しています。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 20px 22px; font-family: &#39;Consolas&#39;, &#39;Courier New&#39;, monospace; font-size: 14px; overflow-x: auto; margin: 24px 0; line-height: 1.65; box-shadow: 0 4px 14px rgba(0,0,0,0.2);&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;# docker-compose.yml （セキュアな多層防御ネットワーク構成）&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;version:&lt;/span&gt; &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&#39;3.8&#39;&lt;/span&gt;

&lt;span style=&quot;color: #38bdf8;&quot;&gt;services:&lt;/span&gt;
  &lt;span style=&quot;color: #64748b;&quot;&gt;# 1. C# Web API サービス（外部からのアクセス窓口）&lt;/span&gt;
  &lt;span style=&quot;color: #f472b6;&quot;&gt;web-api:&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;build:&lt;/span&gt;
      &lt;span style=&quot;color: #38bdf8;&quot;&gt;context:&lt;/span&gt; &lt;span style=&quot;color: #a5f3fc;&quot;&gt;.&lt;/span&gt;
      &lt;span style=&quot;color: #38bdf8;&quot;&gt;dockerfile:&lt;/span&gt; &lt;span style=&quot;color: #a5f3fc;&quot;&gt;Dockerfile&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;container_name:&lt;/span&gt; &lt;span style=&quot;color: #a5f3fc;&quot;&gt;order-web-api&lt;/span&gt;
    &lt;span style=&quot;color: #64748b;&quot;&gt;# ホストの8080ポートをコンテナの8080へ転送（外部公開）&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;ports:&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- &quot;8080:8080&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;environment:&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- ASPNETCORE_ENVIRONMENT=Production&lt;/span&gt;
      &lt;span style=&quot;color: #64748b;&quot;&gt;# 内部DNS名 &quot;sql-server&quot; で安全に接続！&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- ConnectionStrings__DefaultConnection=Server=sql-server,1433;Database=OrderDb;User Id=sa;Password=${DB_PASSWORD};TrustServerCertificate=True;&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;networks:&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- frontend-net&lt;/span&gt;   &lt;span style=&quot;color: #64748b;&quot;&gt;# クライアント通信用&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- backend-net&lt;/span&gt;    &lt;span style=&quot;color: #64748b;&quot;&gt;# DB内部通信用&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;depends_on:&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- sql-server&lt;/span&gt;

  &lt;span style=&quot;color: #64748b;&quot;&gt;# 2. SQL Server サービス（内部専用・外部完全遮断）&lt;/span&gt;
  &lt;span style=&quot;color: #f472b6;&quot;&gt;sql-server:&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;image:&lt;/span&gt; &lt;span style=&quot;color: #a5f3fc;&quot;&gt;mcr.microsoft.com/mssql/server:2022-latest&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;container_name:&lt;/span&gt; &lt;span style=&quot;color: #a5f3fc;&quot;&gt;order-sql-db&lt;/span&gt;
    &lt;span style=&quot;color: #64748b;&quot;&gt;# ⚠️ ここに ports: - &quot;1433:1433&quot; を絶対に書かない！&lt;/span&gt;
    &lt;span style=&quot;color: #64748b;&quot;&gt;# （ホストへのポート公開を遮断し、内部ネットワークからのみアクセスを許可）&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;environment:&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- ACCEPT_EULA=Y&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- MSSQL_SA_PASSWORD=${DB_PASSWORD}&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;volumes:&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- sql-data:/var/opt/mssql/data&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;networks:&lt;/span&gt;
      &lt;span style=&quot;color: #a5f3fc;&quot;&gt;- backend-net&lt;/span&gt;    &lt;span style=&quot;color: #64748b;&quot;&gt;# 内部ネットワークのみに所属！&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# ネットワーク定義（ユーザー定義ブリッジ）&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;networks:&lt;/span&gt;
  &lt;span style=&quot;color: #f472b6;&quot;&gt;frontend-net:&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;driver:&lt;/span&gt; &lt;span style=&quot;color: #a5f3fc;&quot;&gt;bridge&lt;/span&gt;
  &lt;span style=&quot;color: #f472b6;&quot;&gt;backend-net:&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;driver:&lt;/span&gt; &lt;span style=&quot;color: #a5f3fc;&quot;&gt;bridge&lt;/span&gt;

&lt;span style=&quot;color: #38bdf8;&quot;&gt;volumes:&lt;/span&gt;
  &lt;span style=&quot;color: #f472b6;&quot;&gt;sql-data:&lt;/span&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;border-left: 4px solid #512bd4; padding-left: 12px; margin-top: 30px; color: #512bd4; font-size: 18.5px;&quot;&gt;
        C#（ASP.NET Core）側の接続設定（appsettings.json）
    &lt;/h3&gt;
    &lt;p&gt;
        C# の `appsettings.json` や環境変数では、IPアドレスではなく `Server=sql-server,1433` とサービス名（またはコンテナ名）を指定するだけでOKです。&lt;br/&gt;
        Dockerの組み込みDNSが自動的にコンテナ内部のIPアドレスへ解決してくれます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 20px 22px; font-family: &#39;Consolas&#39;, &#39;Courier New&#39;, monospace; font-size: 14px; overflow-x: auto; margin: 24px 0; line-height: 1.65; box-shadow: 0 4px 14px rgba(0,0,0,0.2);&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;// appsettings.json&lt;/span&gt;
{
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;&quot;ConnectionStrings&quot;&lt;/span&gt;: {
    &lt;span style=&quot;color: #64748b;&quot;&gt;// ホスト名にDocker Composeのサービス名 &quot;sql-server&quot; を指定！&lt;/span&gt;
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;&quot;DefaultConnection&quot;&lt;/span&gt;: &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;Server=sql-server,1433;Database=OrderDb;User Id=sa;Password=YourStrong@Pass123;TrustServerCertificate=True;&quot;&lt;/span&gt;
  },
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;&quot;Logging&quot;&lt;/span&gt;: {
    &lt;span style=&quot;color: #38bdf8;&quot;&gt;&quot;LogLevel&quot;&lt;/span&gt;: {
      &lt;span style=&quot;color: #38bdf8;&quot;&gt;&quot;Default&quot;&lt;/span&gt;: &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;Information&quot;&lt;/span&gt;,
      &lt;span style=&quot;color: #38bdf8;&quot;&gt;&quot;Microsoft.AspNetCore&quot;&lt;/span&gt;: &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;Warning&quot;&lt;/span&gt;
    }
  }
}
    &lt;/div&gt;

    &lt;!-- 第5章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;5&lt;/span&gt;
        現場必須の docker network CLIコマンド＆トラブルシューティング
    &lt;/h2&gt;

    &lt;p&gt;
        Dockerネットワークを調査・運用する際、トラブルシューティングで毎日叩く頻出コマンドを整理しました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 20px 22px; font-family: &#39;Consolas&#39;, &#39;Courier New&#39;, monospace; font-size: 14px; overflow-x: auto; margin: 24px 0; line-height: 1.7; box-shadow: 0 4px 14px rgba(0,0,0,0.2);&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;# 1. 存在するネットワークの一覧を表示&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker network ls&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 2. 独自のユーザー定義ブリッジを新規作成&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker network create --driver bridge my-company-net&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 3. ネットワークの詳細（参加コンテナ一覧、割り当てIP、サブネット等）をJSONで確認&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker network inspect my-company-net&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 4. 稼働中のコンテナを別のネットワークに追加接続&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker network connect my-company-net order-web-api&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 5. コンテナをネットワークから切断&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker network disconnect my-company-net order-web-api&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 6. 未使用の孤立ネットワークを一括クリーンアップ&lt;/span&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;docker network prune -f&lt;/span&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #fffbeb; border-left: 5px solid #f59e0b; padding: 18px 22px; border-radius: 6px; margin: 28px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #b45309; font-size: 16.5px;&quot;&gt;🛠️ トラブルシューティング：「コンテナ名で通信できない！」ときのチェックリスト&lt;/h4&gt;
        &lt;ol style=&quot;margin: 0; padding-left: 20px; color: #92400e; font-size: 14.5px; line-height: 1.8;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;同じユーザー定義ネットワークに所属しているか？&lt;/strong&gt;&lt;br/&gt;
                `docker network inspect &lt;ネットワーク名&gt;` を実行し、双方のコンテナ名が `Containers` セクションに存在するか確認してください。
            &lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;デフォルトブリッジ（bridge/docker0）で動いていないか？&lt;/strong&gt;&lt;br/&gt;
                `docker network ls` で確認し、コンテナがデフォルトブリッジに繋がっている場合は組み込みDNSが無効です。ユーザー定義ネットワークを作成して移行しましょう。
            &lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;コンテナ内から名前解決テストを行う:&lt;/strong&gt;&lt;br/&gt;
                `docker exec -it order-web-api nslookup sql-server` や `curl -v http://sql-server:1433` を叩き、DNS解決が成功しているかを内部から切り分けます。
            &lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;!-- 第6章 --&gt;
    &lt;h2 style=&quot;border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; color: #0f172a; font-size: 23px; display: flex; align-items: center;&quot;&gt;
        &lt;span style=&quot;background: #0db7ed; color: white; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; margin-right: 12px; font-weight: bold;&quot;&gt;6&lt;/span&gt;
        第7部開幕！理解度チェッククイズ
    &lt;/h2&gt;

    &lt;p&gt;本日の重要ポイントを3問のクイズでおさらいしましょう！ 各枠をクリックすると正解と解説が展開します。&lt;/p&gt;

    &lt;!-- クイズ1 --&gt;
    &lt;details style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 16px 20px; margin: 18px 0; cursor: pointer;&quot;&gt;
        &lt;summary style=&quot;font-weight: bold; color: #0f172a; font-size: 16px;&quot;&gt;
            Q1: デフォルトブリッジ（docker0）とユーザー定義ブリッジ（User-defined Bridge）の決定的な違いとして「正しいもの」はどれでしょうか？
        &lt;/summary&gt;
        &lt;div style=&quot;margin-top: 14px; padding-top: 14px; border-top: 1px dashed #cbd5e1; color: #334155; font-size: 15px; line-height: 1.8;&quot;&gt;
            &lt;p&gt;&lt;strong style=&quot;color: #2563eb;&quot;&gt;正解: ユーザー定義ブリッジでは、Docker組み込みDNSによるコンテナ名の自動名前解決が有効になる。&lt;/strong&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;【解説】:&lt;/strong&gt; デフォルトブリッジではコンテナ名による名前解決（DNS）が無効化されているため、コンテナ名（例: `sql-server`）での通信ができません。ユーザー定義ブリッジを作成してコンテナを所属させることで、127.0.0.11の組み込みDNSが自動起動し、コンテナ名での安定した相互通信が可能になります。&lt;/p&gt;
        &lt;/div&gt;
    &lt;/details&gt;

    &lt;!-- クイズ2 --&gt;
    &lt;details style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 16px 20px; margin: 18px 0; cursor: pointer;&quot;&gt;
        &lt;summary style=&quot;font-weight: bold; color: #0f172a; font-size: 16px;&quot;&gt;
            Q2: Web APIコンテナからSQL Serverコンテナへ接続する場合、SQL Server側の `docker-compose.yml` 定義として最もセキュアな設計はどれでしょうか？
        &lt;/summary&gt;
        &lt;div style=&quot;margin-top: 14px; padding-top: 14px; border-top: 1px dashed #cbd5e1; color: #334155; font-size: 15px; line-height: 1.8;&quot;&gt;
            &lt;p&gt;&lt;strong style=&quot;color: #2563eb;&quot;&gt;正解: ports 定義（ポート転送）を書かず、Web APIと同じ内部ネットワーク（backend-net等）にのみ所属させる。&lt;/strong&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;【解説】:&lt;/strong&gt; 同じDockerネットワークに所属するコンテナ同士は、ホストへポートを転送（公開）しなくても、コンテナ内のポート（1433）に直接通信できます。SQL Serverの `ports: - &quot;1433:1433&quot;` を外すことで、ホストマシンや外部インターネットからの不正アクセス経路を完全に遮断できます。&lt;/p&gt;
        &lt;/div&gt;
    &lt;/details&gt;

    &lt;!-- クイズ3 --&gt;
    &lt;details style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 16px 20px; margin: 18px 0; cursor: pointer;&quot;&gt;
        &lt;summary style=&quot;font-weight: bold; color: #0f172a; font-size: 16px;&quot;&gt;
            Q3: ネットワークドライバー「host」の特徴として誤っているものはどれでしょうか？
        &lt;/summary&gt;
        &lt;div style=&quot;margin-top: 14px; padding-top: 14px; border-top: 1px dashed #cbd5e1; color: #334155; font-size: 15px; line-height: 1.8;&quot;&gt;
            &lt;p&gt;&lt;strong style=&quot;color: #dc2626;&quot;&gt;正解（誤っている説明）: hostドライバーを使えば、ホスト側で既に80番ポートが使われていても、コンテナ側で自由に80番ポートを独立して利用できる。&lt;/strong&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;【解説】:&lt;/strong&gt; hostドライバーはホストマシンのネットワーク名前空間を直接共有するため、ネットワークオーバーヘッドがない反面、ポートの分離が一切行われません。ホスト側で既に80番ポートがバインドされている場合、コンテナ側で80番ポートを起動しようとするとポート衝突エラー（Address already in use）で起動に失敗します。&lt;/p&gt;
        &lt;/div&gt;
    &lt;/details&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); color: #ffffff; border-radius: 10px; padding: 26px 28px; margin: 45px 0 20px 0; box-shadow: 0 8px 24px rgba(15,23,42,0.18);&quot;&gt;
        &lt;div style=&quot;display: flex; align-items: center; margin-bottom: 12px;&quot;&gt;
            &lt;span style=&quot;font-size: 24px; margin-right: 12px;&quot;&gt;🚀&lt;/span&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 4px; padding: 3px 10px; font-size: 12.5px; font-weight: bold; letter-spacing: 0.5px;&quot;&gt;次回予告&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3 style=&quot;margin: 0 0 12px 0; color: #38bdf8; font-size: 20px;&quot;&gt;
            【Day 33】コンテナ間通信とポートマッピング（-p / EXPOSE）の真実！
        &lt;/h3&gt;
        &lt;p style=&quot;margin: 0; font-size: 15px; line-height: 1.85; color: #cbd5e1;&quot;&gt;
            今回の講義で、Dockerネットワークの土台となる仮想ブリッジと多層防御の概念を完璧にマスターしました！&lt;br/&gt;
            次回は、コンテナ通信のもう1つの超重要テーマ&lt;strong&gt;『ポートマッピング（-p）と Dockerfileの EXPOSE 命令の決定的な違い』&lt;/strong&gt;を徹底深掘りします！&lt;br/&gt;
            &lt;em&gt;「Dockerfileに EXPOSE 80 と書いたのに、なぜホストのブラウザから開けないのか？」「-p 8080:80 の左と右はどう決めるのか？」&lt;/em&gt;&lt;br/&gt;
            現場エンジニアが最も混乱するポート転送の仕組みを、パケットの流れとともに完全解明します。次回もお楽しみに！
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/8477220137955428868/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-32dockerbridge-host-none-dnsc-web.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/8477220137955428868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/8477220137955428868'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-32dockerbridge-host-none-dnsc-web.html' title='【Day 32】Dockerネットワークの仕組み（Bridge, Host, None） 〜仮想ブリッジによる通信分離・デフォルトブリッジの罠・組み込みDNS・C# Web APIとDBの多層防御設計〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1wCFIZNg1H9FgTPS4mKbpc62hfT2EdS-Q=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-5528836301144115317</id><published>2026-10-27T18:11:12.083+09:00</published><updated>2026-10-27T18:11:12.083+09:00</updated><title type='text'>【Day 29】git blame &amp; git log -L でC#コードの「犯人・導入理由」を完全特定</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1A-OIf-_uWW05VIe8QRs9Ovj85SCB2Rd_&quot; alt=&quot;Day 29 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 29】git blame &amp; git log -L でC#コードの「犯人・導入理由」を完全特定&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 28では、必要な行だけをインデックスに選別してアトミックなコミットを作る&lt;strong&gt;「git add -p」&lt;/strong&gt;の部分ステージング術を学びました。&lt;br/&gt;
            そして本日のDay 29は、保守・運用・レガシーコード調査の現場でエンジニアの調査スピードを10倍に引き上げる極意——&lt;strong&gt;【git blame &amp; git log -L でC#コードの「犯人・導入理由」を完全特定】&lt;/strong&gt;をお届けします！&lt;br/&gt;
            「他人が書いたC#のビジネスロジックを読んでいるとき、『なぜこんな不自然なif文があるんだ？』『このハードコードされた閾値は何のために存在するんだ？』と頭を抱えたことはありませんか？」&lt;br/&gt;
            「そして『誰だこんな汚いコードを書いたやつは！消してしまえ！』と短絡的に削除してしまい、実は過去の重大な障害を防ぐための命綱ガードだったことで、障害を再発させて青ざめた経験はありませんか？」&lt;br/&gt;
            プロのエンジニアに必要なのは、怒りではなく&lt;strong&gt;「コード考古学（Code Archaeology）」&lt;/strong&gt;の視点です。&lt;br/&gt;
            Gitのコマンドや最新のGUI拡張機能を駆使すれば、怪しい1行や特定のC#メソッドが&lt;strong&gt;「いつ・誰が・どのコミットで・どのような仕様・チケット（Issue/PR）の理由で書かれたのか」&lt;/strong&gt;を数秒でタイムスリップして解明できます！&lt;br/&gt;
            SVN時代の重いblameとは次元の違う、Gitならではの超高速コード調査テクニックをマスターしましょう！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        ソフトウェア開発において、コードを新しく書く時間よりも「他人の書いた既存コードを読む時間・調べる時間」の方が圧倒的に長いと言われています。&lt;br/&gt;
        特に数年間運用されてきたC#の大規模システムでは、複雑怪奇なビジネスルールや例外処理が無数に積み重なっています。&lt;br/&gt;
        本日は、Gitが誇る2大調査コマンド &lt;code&gt;git blame&lt;/code&gt; と &lt;code&gt;git log -L&lt;/code&gt;、そしてVS Code GitLensなどのGUIツールを駆使して、コードの真意を鮮やかにあぶり出す技を身につけます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;SVN blame と Gitコード考古学の決定的違い（速度、コミット文脈、Issue/PR直結）を理解する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git blame&lt;/code&gt; コマンドで怪しい行のコミットハッシュ・コミット者・日時を瞬時に特定する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;-w&lt;/code&gt;（空白無視）や &lt;code&gt;-C&lt;/code&gt;（ファイル間移動追跡）オプションで、表面的な修正に惑わされない真の作成者を暴く&lt;/li&gt;
            &lt;li&gt;リファクタリングで行番号がズレても関数の進化史だけを時系列抽出する &lt;code&gt;git log -L :メソッド名:ファイル&lt;/code&gt; の神威を体得する&lt;/li&gt;
            &lt;li&gt;VS Code拡張「GitLens」と「TortoiseGit Blame」を活用し、日常のエディタ操作から1クリックでGitHub PRにジャンプする&lt;/li&gt;
            &lt;li&gt;実戦C#シナリオを通じて、「謎のガード節」の導入背景を解明し、事故を未然に防ぐ安全な調査フローを確立する&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: SVN blame vs Git コード考古学 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】SVN blame vs Git コード考古学の決定的違い&lt;/h2&gt;
    &lt;p&gt;
        Subversion (SVN) にも &lt;code&gt;svn blame&lt;/code&gt;（TortoiseSVNのBlame機能）がありましたが、Gitのコード調査能力はそれを遥かに凌駕しています。
    &lt;/p&gt;

    &lt;!-- 図解① --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1ud4yalfoLm0PX-Hh742aC3eNaz43VJO-&quot; alt=&quot;SVN blame vs Git コード考古学の比較&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】中央サーバー通信で重いSVN vs ローカル即時応答＆Issue/PRまで一気通貫で追跡できるGitコード考古学&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        SVNとGitにおけるコード調査の体験差は、以下の3点に集約されます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15.5px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #f1f5f9; border-bottom: 2px solid #cbd5e1;&quot;&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 22%;&quot;&gt;比較項目&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 38%; color: #991b1b;&quot;&gt;SVN blame&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 40%; color: #1e40af;&quot;&gt;Git コード考古学&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;調査スピード&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;中央サーバー通信必須。巨大ファイルでは数秒〜数十秒待たされる。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;ローカル完全完結。数千行のC#ファイルでも0.1秒で即座に応答。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;得られる情報&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;リビジョン番号とユーザー名のみ。前後の文脈を追うには別ログ検索が必要。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;コミットメッセージ、ブランチ履歴、PR/Issue番号（#123）まで一気通貫。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;関数の歴史追跡&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;不可（行番号単位の履歴しか追えず、行がズレると破綻）。&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #166534; font-weight: bold;&quot;&gt;&lt;code&gt;git log -L&lt;/code&gt; でメソッド単位の誕生から現在までのDiff履歴を完全追跡。&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- セクション③: git blame コマンドによる怪しい1行の特定 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】git blame コマンドによる怪しい1行の特定&lt;/h2&gt;
    &lt;p&gt;
        まずは最も基本となる &lt;code&gt;git blame&lt;/code&gt; コマンドです。英語の「blame（〜を責める、罪を着せる）」という物騒な単語がついていますが、目的は人を責めることではなく、&lt;strong&gt;「そのコードを書いた作者（仕様を知る人物）と導入コミットの背景を特定すること」&lt;/strong&gt;です。
    &lt;/p&gt;

    &lt;!-- 図解② --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/10A6f9NlqPBQ60QM64X9kuLGwmFcpxpaM&quot; alt=&quot;git blame による怪しい1行の特定フロー&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】git blame -L で行範囲を絞り込み、コミットハッシュ・作者・日時・コード行を一撃特定&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        ファイル全体に &lt;code&gt;git blame&lt;/code&gt; を実行すると何千行もの出力が流れてしまうため、実戦では必ず &lt;code&gt;-L&lt;/code&gt; オプションで対象の行範囲を指定します。
    &lt;/p&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;# 構文: git blame -L 開始行,終了行 ファイル名
$ git blame -L 45,55 Services/OrderService.cs

e4f8a12c (Yamada Taro 2025-04-12 14:22:10 +0900 45)     // キャンペーン期間中の割引額ガード
e4f8a12c (Yamada Taro 2025-04-12 14:22:10 +0900 46)     if (discountAmount &gt; MaxCampaignDiscount)
e4f8a12c (Yamada Taro 2025-04-12 14:22:10 +0900 47)     {
e4f8a12c (Yamada Taro 2025-04-12 14:22:10 +0900 48)         discountAmount = MaxCampaignDiscount;
e4f8a12c (Yamada Taro 2025-04-12 14:22:10 +0900 49)     }
8a3d901b (Sato Kenji  2024-11-03 09:15:33 +0900 50)     return finalPrice - discountAmount;&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;
        出力の各列は左から順に次の情報を表しています：
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 24px; line-height: 1.85;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;コミットハッシュ（短縮）:&lt;/strong&gt; &lt;code&gt;e4f8a12c&lt;/code&gt;（その行を最後に変更したコミット）&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;コミット作成者:&lt;/strong&gt; &lt;code&gt;Yamada Taro&lt;/code&gt;（その変更を行ったエンジニア）&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;コミット日時:&lt;/strong&gt; &lt;code&gt;2025-04-12 14:22:10 +0900&lt;/code&gt;（いつ変更されたか）&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;行番号とコード実体:&lt;/strong&gt; &lt;code&gt;46) if (discountAmount &gt; MaxCampaignDiscount)&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #3b82f6; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #1d4ed8; font-size: 16px;&quot;&gt;💡 プロが使う git blame の神オプション&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;code&gt;git blame -w -L 45,55 File.cs&lt;/code&gt;: &lt;strong&gt;-w (ignore-whitespace)&lt;/strong&gt;。&lt;br/&gt;インデントの変更やタブ/スペースの置換、改行コード変更を無視し、実質的なコードを書いた真の作者を表示します。&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git blame -M -L 45,55 File.cs&lt;/code&gt;: &lt;strong&gt;-M (detect moved lines)&lt;/strong&gt;。&lt;br/&gt;同一ファイル内で別の行からコピペ・移動された行を検知し、元の作成コミットまで遡ります。&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git blame -C -L 45,55 File.cs&lt;/code&gt;: &lt;strong&gt;-C (detect copied lines)&lt;/strong&gt;。&lt;br/&gt;別ファイルから移植されたコード行であっても、コピー元のオリジナルコミットまで追跡します。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション④: git log -L で関数まるごとの歴史を追跡 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【図解】git log -L で関数まるごとの歴史を追跡（コード考古学の極意）&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;git blame&lt;/code&gt; は非常に便利ですが、大きな弱点があります。&lt;br/&gt;
        それは、&lt;strong&gt;「直近でその行に触れた1つのコミットしか見えない」&lt;/strong&gt;という点です。&lt;br/&gt;
        例えば、他のエンジニアがコードクリーンアップで変数名を少し変更しただけで、blameの作者はそのエンジニアの名前で上書きされてしまい、「この関数がそもそもどうやって作られ、どんな変遷をたどってきたのか」が分からなくなってしまいます。
    &lt;/p&gt;
    &lt;p&gt;
        そこで真価を発揮するのが、Gitの最高峰機能 &lt;strong&gt;&lt;code&gt;git log -L&lt;/code&gt;&lt;/strong&gt; です！
    &lt;/p&gt;

    &lt;!-- 図解③ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1JuVCRtWw5dXHHruVsm8jllZDON6mYup6&quot; alt=&quot;git log -L による関数の歴史追跡&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】行番号のズレを完全無視！git log -L :メソッド名:ファイル で関数の誕生から現在までの進化Diffを時系列抽出&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        &lt;code&gt;git log -L&lt;/code&gt; には、行番号範囲だけでなく&lt;strong&gt;「関数名（メソッド名）」&lt;/strong&gt;を直接指定する構文が用意されています！
    &lt;/p&gt;

    &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 18px; border-radius: 8px; overflow-x: auto; font-size: 14.5px; line-height: 1.6;&quot;&gt;&lt;code&gt;# 構文: git log -L :メソッド名:ファイル名
$ git log -L :CalculateDiscount:Services/OrderService.cs&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;
        これを実行すると、GitがC#の構文を認識し、&lt;strong&gt;他の行が何千行追加・削除されて行番号がどれだけズレても、&lt;code&gt;CalculateDiscount&lt;/code&gt; メソッド自体の誕生から最新の変更までの差分（Diff）だけを時系列に沿って逆順に一挙表示&lt;/strong&gt;してくれます！
    &lt;/p&gt;

    &lt;div style=&quot;background: #f0fdf4; border-left: 5px solid #22c55e; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #15803d; font-size: 16.5px;&quot;&gt;✨ git log -L がもたらす圧倒的メリット&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85; color: #14532d;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;行番号の変動に100%影響されない:&lt;/strong&gt; クラスの上に何百行コードが足されても、メソッドの境界を自動追跡してくれる。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;成長の変遷（進化論）が丸見えになる:&lt;/strong&gt; 「初期リリース（v1.0）→ 税率対応（v1.5）→ キャンペーン上限追加（v2.0）」という機能進化の過程が時系列差分で理解できる。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;ノイズの完全排除:&lt;/strong&gt; クラス内の他のメソッドの変更が一切混ざらないため、調べたい関数の歴史だけに集中できる。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑤: VS Code GitLens と TortoiseGit Blame --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【図解】VS Code GitLens と TortoiseGit Blame による視覚的調査&lt;/h2&gt;
    &lt;p&gt;
        日常のコーディングにおいて、毎回コマンドを叩くのは手間に感じることもあります。&lt;br/&gt;
        現代のプロ開発現場では、GUIツールを巧みに組み合わせて瞬時にコード考古学を実践しています。
    &lt;/p&gt;

    &lt;!-- 図解④ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1wrKLoshAlTsveaPg22ExArWRN5qrj57k&quot; alt=&quot;VS Code GitLens と TortoiseGit Blame のGUI操作&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】エディタにカーソルを合わせるだけでPR直結のGitLens ＆ Windows右クリックで視覚的色分け閲覧のTortoiseGit&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e3a8a; font-size: 19px; margin-top: 25px;&quot;&gt;1. VS Code 拡張機能「GitLens」の威力&lt;/h3&gt;
    &lt;p&gt;
        VS Codeで開発しているエンジニアにとって、もはや必須ツールと言えるのが「GitLens」です。&lt;br/&gt;
        エディタ上でコードの任意の行にカーソルを置くだけで、行の末尾に薄いグレーの文字で次のようなアノテーションが自動表示されます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #1e293b; color: #94a3b8; padding: 14px 18px; border-radius: 6px; font-family: monospace; font-size: 14px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;if (discountAmount &gt; MaxCampaignDiscount)&lt;/span&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;Yamada Taro, 6 months ago • Bugfix: 防止上限超過 (#402)&lt;/span&gt;
    &lt;/div&gt;
    &lt;p&gt;
        さらに、そのテキストの上にマウスをホバーすると、コミットメッセージの全文、コミット詳細、そして&lt;strong&gt;GitHubのPull Requestへの直接リンク&lt;/strong&gt;がポップアップ表示されます！&lt;br/&gt;
        「カーソルを置く → ポップアップのPRリンクをクリック → 当時の仕様策定の議論やQA結果を読む」という一連の流れがわずか3秒で完了します。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e3a8a; font-size: 19px; margin-top: 25px;&quot;&gt;2. Windowsエンジニアの味方「TortoiseGit Blame」&lt;/h3&gt;
    &lt;p&gt;
        Windows環境でエクスプローラーを活用している場合、ファイルを右クリックして &lt;strong&gt;[TortoiseGit] → [Blame]&lt;/strong&gt; を選択するだけで、専用のグラフィカルなBlameビューアが起動します。&lt;br/&gt;
        コミット時期によって行番号の背景色がグラデーション（新しい行は赤系、古い行は青系）で色分けされるため、「どの部分が最近触られたコードか」が一目で視覚的に直感把握できます。
    &lt;/p&gt;

    &lt;!-- セクション⑥: C#現場実戦シナリオ --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ C#現場実戦シナリオ：謎のガード節をコード考古学で解明せよ&lt;/h2&gt;
    &lt;p&gt;
        ここで、実際のC#業務開発でありがちなトラブル事例を見てみましょう。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 20px; margin: 20px 0;&quot;&gt;
        &lt;strong style=&quot;color: #0f172a; font-size: 17px;&quot;&gt;🏢 実戦シナリオ: ECサイトの注文割引計算クラス（OrderService.cs）&lt;/strong&gt;
        &lt;p style=&quot;margin-top: 10px; line-height: 1.8;&quot;&gt;
            新しくプロジェクトに配属された新任エンジニアの佐藤さんは、&lt;code&gt;OrderService.cs&lt;/code&gt; をリファクタリング中、次のような奇妙なコードを見つけました。
        &lt;/p&gt;
        &lt;pre style=&quot;background: #0f172a; color: #f8fafc; padding: 14px; border-radius: 6px; font-size: 14px; line-height: 1.6;&quot;&gt;&lt;code&gt;public decimal CalculateDiscount(Order order)
{
    decimal discount = 0;
    // ... 各種クーポン計算ロジック ...

    // ▼ 佐藤さんの疑問: 「なぜここで突然10,000円で頭打ちにするんだ？ 仕様書にはそんなこと書いてないぞ？」
    if (order.CustomerType == CustomerType.VIP &amp;&amp; discount &gt; 10000m)
    {
        discount = 10000m; // 謎のハードコード！？ 消してしまおうか？
    }

    return discount;
}&lt;/code&gt;&lt;/pre&gt;
        &lt;p style=&quot;line-height: 1.8;&quot;&gt;
            仕様書を読んでも「VIP割引に1万円の上限がある」という記述は見当たりません。&lt;br/&gt;
            ここで&lt;strong&gt;「仕様書にないからバグだろう」と勝手に消してしまうと大事故（二重割引で赤字販売）&lt;/strong&gt;になります！&lt;br/&gt;
            佐藤さんはコード考古学の技を発動しました。
        &lt;/p&gt;
        &lt;ol style=&quot;padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;code&gt;git blame -L 8,11 Services/OrderService.cs&lt;/code&gt; を実行。&lt;/li&gt;
            &lt;li&gt;コミットハッシュ &lt;code&gt;d9a1f24e&lt;/code&gt; と作者「Yamada」を特定。&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git show d9a1f24e&lt;/code&gt; でコミットメッセージを確認すると……&lt;br/&gt;
                &lt;code&gt;&quot;Hotfix: VIP会員がブラックフライデークーポンを併用した際に割引率が100%を超えて販売価格がマイナスになる脆弱性を緊急防御 (Issue #882)&quot;&lt;/code&gt; と記述されていた！
            &lt;/li&gt;
            &lt;li&gt;GitHubの Issue #882 を開くと、「次期基盤移行までの暫定防壁として1万円上限を適用する。恒久対応は2026年秋リリース」というビジネス判断の経緯が記録されていた！&lt;/li&gt;
        &lt;/ol&gt;
        &lt;p style=&quot;margin-bottom: 0; line-height: 1.8; color: #1e3a8a; font-weight: bold;&quot;&gt;
            👉 調査にかかった時間はわずか2分。佐藤さんは勝手な削除を思いとどまり、チームリーダーと相談して恒久対応の設計に着手することができました！
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑦: まとめ --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑦ 📌 まとめ・理解したい最重要ポイント&lt;/h2&gt;
    &lt;p&gt;
        本日の講義の総まとめです。コード考古学は、他人のコードを尊重し、システムの安全を守るための必須教養です。
    &lt;/p&gt;

    &lt;div style=&quot;background: #eff6ff; border: 2px solid #93c5fd; border-radius: 8px; padding: 20px 24px; margin: 25px 0;&quot;&gt;
        &lt;strong style=&quot;color: #1e40af; font-size: 18px;&quot;&gt;📌 Day 29 の最重要チェックリスト&lt;/strong&gt;
        &lt;ol style=&quot;margin: 12px 0 0 0; padding-left: 22px; line-height: 1.9; color: #1e293b;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;怪しいコードを見たら「怒る前に blame」:&lt;/strong&gt;&lt;br/&gt;
                &lt;code&gt;git blame -L 開始行,終了行 ファイル名&lt;/code&gt; で、作者・日時・コミットハッシュを特定し、コミットメッセージやチケット番号から「当時の仕様決定の経緯」を必ず確認する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;表面的なフォーマット変更はオプションで貫通せよ:&lt;/strong&gt;&lt;br/&gt;
                &lt;code&gt;git blame -w&lt;/code&gt;（空白・インデント無視）や &lt;code&gt;-M&lt;/code&gt;（同一ファイル内移動検出）を活用し、真のコード作成者を暴く。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;関数の歴史は &lt;code&gt;git log -L :メソッド名:ファイル&lt;/code&gt; でタイムスリップ:&lt;/strong&gt;&lt;br/&gt;
                行番号のズレを無視し、その関数が誕生してから現在に至るまでの変遷Diffだけをピンポイントで時系列解剖する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;VS Code GitLens ＆ TortoiseGit Blame を日常に組み込め:&lt;/strong&gt;&lt;br/&gt;
                エディタ上でカーソルを置くだけでPRまでジャンプできる快適な開発環境を構築し、調査スピードを劇的に加速させる。&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #64748b; padding: 16px 20px; margin: 30px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #334155; font-size: 16.5px;&quot;&gt;🚀 次回予告【Day 30】&lt;/strong&gt;&lt;br/&gt;
        次回はいよいよ第6部の集大成——&lt;strong&gt;【git bisect で原因不明のバグ混入コミットを二分探索で自動特定】&lt;/strong&gt;を解説します！&lt;br/&gt;
        「先週までは動いていたはずなのに、いつの間にかエラーが出るようになった……数百個あるコミットのどれが原因だ？」&lt;br/&gt;
        そんな絶望的な状況を、Gitがテストコードを自動実行しながら二分探索（バイナリサーチ）で秒速特定してくれる魔法のような神コマンドの全貌を解き明かします。お楽しみに！
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/5528836301144115317/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-29git-blame-git-log-l-c.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/5528836301144115317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/5528836301144115317'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-29git-blame-git-log-l-c.html' title='【Day 29】git blame &amp; git log -L でC#コードの「犯人・導入理由」を完全特定'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1A-OIf-_uWW05VIe8QRs9Ovj85SCB2Rd_=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-186052056046118328</id><published>2026-10-27T09:22:06.103+09:00</published><updated>2026-10-27T09:22:06.103+09:00</updated><title type='text'>【Day 31】データベース初期データ（シードデータ）の自動投入テクニック 〜新人の手動DBリストアを完全撤廃！ entrypoint-initdb の仕組み、C# EF Core 起動時マイグレーション、ゼロセットアップDB環境の構築〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/133ccBazLc71bAsA6sWpD_owCRuQaZjV2&quot; alt=&quot;Day 31 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 31: データベース初期データ（シードデータ）の自動投入テクニック&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 導入メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: linear-gradient(135deg, #e0f2fe 0%, #f0fdf4 100%); border-left: 6px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0; box-shadow: 0 4px 12px rgba(13,183,237,0.08);&quot;&gt;
        &lt;div style=&quot;font-size: 32px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;font-size: 15.5px; color: #0f172a;&quot;&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; font-weight: bold; color: #0369a1; font-size: 17px;&quot;&gt;「新メンバーがチームに入った日、DB環境構築で丸一日潰していませんか？」&lt;/p&gt;
            &lt;p style=&quot;margin: 0; line-height: 1.8;&quot;&gt;
                前回のDay 30では、「コード・構成（Git）」と「実データ（Volume）」の3層分離原則を徹底解説し、巨大なDBファイルをGitにコミットしてリポジトリを破壊する事故の防止策を学びました。&lt;br/&gt;
                しかし、ここで現場のエンジニアから最も多く寄せられる切実な疑問があります：&lt;br/&gt;
                &lt;strong&gt;『mdfファイルをGitに含めないのは理解できた。では、新人が開発を始めるための初期データ（マスターデータやテスト用データ）はどうやって渡せばいいのか？』&lt;/strong&gt;&lt;br/&gt;
                かつてのオンプレミス現場では、先輩エンジニアがUSBメモリや共有フォルダで数GBのダンプファイルを手渡し、手作業でSSMSからリストアさせていました。&lt;br/&gt;
                しかし現代のコンテナ開発では、&lt;strong&gt;『リポジトリをクローンして docker compose up を1回実行するだけで、必要な初期データがすべて自動投入されたDBが立ち上がる』という「ゼロセットアップDB環境」&lt;/strong&gt; が標準です。&lt;br/&gt;
                本講義では、Docker標準の &lt;code&gt;entrypoint-initdb&lt;/code&gt; の自動実行メカニズムから、C# EF Core による &lt;code&gt;Database.Migrate()&lt;/code&gt; とテストデータ注入テクニックまで、現場で即座に役立つ自動化ノウハウを完全網羅します！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 目次セクション --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 12px; font-size: 17px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 4px; padding: 2px 8px; font-size: 13px; margin-right: 10px;&quot;&gt;INDEX&lt;/span&gt;
            本日の講義カリキュラム
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #475569; font-size: 15px; line-height: 2;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;第1章: USB手動配布の悲劇と「ゼロセットアップDB」の必然性&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第2章: コンテナ初回起動時の自動実行メカニズム（entrypoint-initdb.d）&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第3章: C# EF Core Migration と Database.Migrate() による自動適用&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第4章: チーム開発におけるゼロセットアップDBの Docker Compose 実践構成&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第5章: 現場トラブルシューティング＆ベストプラクティス&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第6章: 第6部総まとめと理解度チェッククイズ（次回予告：第7部 Dockerネットワーク入門）&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第1章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第1章: USB手動配布の悲劇と「ゼロセットアップDB」の必然性&lt;/h2&gt;
        &lt;p&gt;
            多くの開発現場で、新メンバー配属時やPCリプレイス時に次のような光景が繰り返されてきました：
        &lt;/p&gt;
        &lt;ul style=&quot;line-height: 1.8; color: #334155;&quot;&gt;
            &lt;li&gt;先輩社員が「これ、開発用のDBバックアップだから」とUSBメモリを新人に手渡す&lt;/li&gt;
            &lt;li&gt;新人がSQL Server Management Studio（SSMS）を開き、手動で「データベースの復元」を実行&lt;/li&gt;
            &lt;li&gt;「SQL Serverのバージョンが合わない（上位バージョンで作られたbakファイルは下位バージョンに復元不可）」「論理ファイル名のマッピングエラー」「ログインユーザーのSID不整合」などでエラー連発&lt;/li&gt;
            &lt;li&gt;気づけば環境構築だけで新人の入社初日〜2日目が終了してしまう…&lt;/li&gt;
        &lt;/ul&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_31_02_usb_dump_vs_seed_auto.png&quot; alt=&quot;USBダンプ手動配布 vs 自動シード&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】旧来のUSB手動リストア（危険・非効率） vs 現代の初期データ自動投入（安全・爆速）&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;p&gt;
            上図（左側）の通り、手動によるDBダンプ配布には致命的な問題があります。手順の属人化、バージョンの不一致、そして「誰のPCのDBが一番最新の状態か分からない」という深刻な環境ドリフトです。&lt;br/&gt;
            これに対して現代のコンテナ開発が目指すのが、上図（右側）の &lt;strong&gt;「ゼロセットアップDB（Zero-Setup Database）」&lt;/strong&gt; です。&lt;br/&gt;
            新人が行う操作はたった2つ：
        &lt;/p&gt;
        &lt;ol style=&quot;line-height: 1.8; color: #334155;&quot;&gt;
            &lt;li&gt;&lt;code&gt;git clone &amp;lt;リポジトリURL&amp;gt;&lt;/code&gt; でコードを取得する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;docker compose up -d&lt;/code&gt; を実行する&lt;/li&gt;
        &lt;/ol&gt;
        &lt;p&gt;
            これだけで、最新のスキーマ定義、商品マスタ、初期テストユーザーが完璧に整ったデータベースコンテナが自動的に構築されます。人間が手作業でSQLを実行したり、USBメモリを受け渡す必要は1ミリもありません。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第2章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第2章: コンテナ初回起動時の自動実行メカニズム（entrypoint-initdb.d）&lt;/h2&gt;
        &lt;p&gt;
            「コンテナを起動した瞬間に、どうやって初期SQLスクリプトを実行させるのか？」&lt;br/&gt;
            多くの公式データベースイメージ（PostgreSQL、MySQL、MariaDBなど）には、この初期データ自動投入のための標準仕様である &lt;strong&gt;&lt;code&gt;/docker-entrypoint-initdb.d/&lt;/code&gt;&lt;/strong&gt; という仕組みが最初から組み込まれています。
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_31_03_entrypoint_initdb_flow.png&quot; alt=&quot;初期化スクリプト自動実行の流れ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】コンテナ初回起動時における entrypoint-initdb 自動実行フローとVolume判定&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;h3 style=&quot;font-size: 18px; color: #0f172a; margin-top: 24px;&quot;&gt;entrypoint-initdb.d の動作原理&lt;/h3&gt;
        &lt;p&gt;
            上図に示した通り、データベースコンテナの起動スクリプト（&lt;code&gt;docker-entrypoint.sh&lt;/code&gt;）は、内部で次のような厳格な判定を行っています：
        &lt;/p&gt;
        &lt;div style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 18px 20px; margin: 16px 0;&quot;&gt;
            &lt;h4 style=&quot;margin: 0 0 10px 0; color: #0369a1; font-size: 16px;&quot;&gt;🔍 初回起動判定の3ステップロジック&lt;/h4&gt;
            &lt;ol style=&quot;margin: 0; padding-left: 20px; font-size: 14.5px; line-height: 1.8; color: #334155;&quot;&gt;
                &lt;li&gt;&lt;strong&gt;データディレクトリの確認:&lt;/strong&gt; マウントされたVolume（例: &lt;code&gt;/var/lib/postgresql/data&lt;/code&gt;）を検査し、既存のデータベースファイルが存在するかチェックする。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;未初期化（空）の場合のみ実行:&lt;/strong&gt; データが空の場合（初回起動時）、&lt;code&gt;/docker-entrypoint-initdb.d/&lt;/code&gt; 配下に存在する &lt;code&gt;.sql&lt;/code&gt; や &lt;code&gt;.sh&lt;/code&gt; スクリプトを &lt;strong&gt;ファイル名のアルファベット昇順（例: 01-schema.sql ➡ 02-seed.sql）&lt;/strong&gt; で順番に自動実行する。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;データが存在する場合はスキップ:&lt;/strong&gt; 既にデータベースが作成されている場合（2回目以降の &lt;code&gt;docker compose up&lt;/code&gt;）、スクリプトの実行を自動的にスキップし、既存データを完全に保護する。&lt;/li&gt;
            &lt;/ol&gt;
        &lt;/div&gt;

        &lt;p&gt;
            この「Volumeが空の初回起動時のみ実行される」という特性が極めて重要です。日々の開発でコンテナを停止・再起動しても、データが勝手に初期化されたり上書きされて消える心配は一切ありません！
        &lt;/p&gt;

        &lt;h3 style=&quot;font-size: 18px; color: #0f172a; margin-top: 24px;&quot;&gt;SQL Server（MSSQL）における初期スクリプト実行テクニック&lt;/h3&gt;
        &lt;p&gt;
            ここでMicrosoft SQL Server（&lt;code&gt;mcr.microsoft.com/mssql/server&lt;/code&gt;）を扱うC#開発者が必ず突き当たる壁があります：&lt;br/&gt;
            &lt;strong&gt;「SQL Serverの公式イメージには /docker-entrypoint-initdb.d が用意されていない！」&lt;/strong&gt; という事実です。&lt;br/&gt;
            SQL Serverでコンテナ起動時に自動で初期SQLを流し込むには、現場では以下の &lt;strong&gt;「ワンショット初期化コンテナ（initコンテナパターン）」&lt;/strong&gt; を採用するのが最も堅牢で推奨されるベストプラクティスです。
        &lt;/p&gt;

        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 16px 0; overflow-x: auto;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #64748b;&quot;&gt;# docker-compose.yml での init コンテナパターン&lt;/span&gt;
&lt;span style=&quot;color: #7dd3fc;&quot;&gt;services:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;db:&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;image:&lt;/span&gt; mcr.microsoft.com/mssql/server:2022-latest
    &lt;span style=&quot;color: #f472b6;&quot;&gt;environment:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;ACCEPT_EULA=Y&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;MSSQL_SA_PASSWORD=${SA_PASSWORD}&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;volumes:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;sqlserver_data:/var/opt/mssql/data&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;healthcheck:&lt;/span&gt;
      &lt;span style=&quot;color: #f472b6;&quot;&gt;test:&lt;/span&gt; [&lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;CMD-SHELL&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P &quot;$$MSSQL_SA_PASSWORD&quot; -C -Q &#39;SELECT 1&#39; || exit 1&quot;&lt;/span&gt;]
      &lt;span style=&quot;color: #f472b6;&quot;&gt;interval:&lt;/span&gt; 5s
      &lt;span style=&quot;color: #f472b6;&quot;&gt;timeout:&lt;/span&gt; 5s
      &lt;span style=&quot;color: #f472b6;&quot;&gt;retries:&lt;/span&gt; 10

  &lt;span style=&quot;color: #64748b;&quot;&gt;# ★DB本体が健全起動した後に1度だけ実行されて終了する初期化専用サービス&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;db-init:&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;image:&lt;/span&gt; mcr.microsoft.com/mssql-tools
    &lt;span style=&quot;color: #f472b6;&quot;&gt;depends_on:&lt;/span&gt;
      &lt;span style=&quot;color: #cbd5e1;&quot;&gt;db:&lt;/span&gt;
        &lt;span style=&quot;color: #cbd5e1;&quot;&gt;condition:&lt;/span&gt; service_healthy
    &lt;span style=&quot;color: #f472b6;&quot;&gt;volumes:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;./init-scripts:/scripts:ro&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;entrypoint:&lt;/span&gt; &gt;
      /bin/bash -c &quot;
      echo &#39;SQL Server初期化スクリプトを実行中...&#39;;
      /opt/mssql-tools/bin/sqlcmd -S db -U sa -P &quot;$$SA_PASSWORD&quot; -d master -i /scripts/01_create_tables_and_seed.sql;
      echo &#39;初期データの投入が完了しました！&#39;;
      &quot;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;environment:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;SA_PASSWORD=${SA_PASSWORD}&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;restart:&lt;/span&gt; &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;no&quot;&lt;/span&gt;
&lt;/pre&gt;
        &lt;/div&gt;
        &lt;p&gt;
            この構成では、&lt;code&gt;db-init&lt;/code&gt; サービスが &lt;code&gt;depends_on&lt;/code&gt; と &lt;code&gt;service_healthy&lt;/code&gt; により &lt;strong&gt;「SQL Serverがクエリを受け付けられる状態になった瞬間」&lt;/strong&gt; を検知して自動実行されます。SQLの実行が終われば自動的に停止するため、余計なリソースを消費しません。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第3章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第3章: C# EF Core Migration と Database.Migrate() による自動適用&lt;/h2&gt;
        &lt;p&gt;
            初期データを投入するもう一つの強力なアプローチが、.NET / C# の標準ORMである &lt;strong&gt;Entity Framework Core（EF Core）&lt;/strong&gt; を活用したコードベースのマイグレーションとシーディングです。
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_31_04_efcore_migration_vs_sql.png&quot; alt=&quot;EF Coreマイグレーション vs SQL配置&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】C#現場でのベストプラクティス：EF CoreマイグレーションとSQLスクリプトの役割分担&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;h3 style=&quot;font-size: 18px; color: #0f172a; margin-top: 24px;&quot;&gt;Program.cs での起動時マイグレーション&lt;/h3&gt;
        &lt;p&gt;
            C# Web API アプリケーションの起動時（&lt;code&gt;Program.cs&lt;/code&gt;）に以下のコードを記述しておくことで、コンテナ起動時に自動で最新マイグレーションをSQL Serverに適用させることができます：
        &lt;/p&gt;

        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 16px 0; overflow-x: auto;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #64748b;&quot;&gt;// Program.cs （.NET 8 / 9 形式）&lt;/span&gt;
&lt;span style=&quot;color: #f472b6;&quot;&gt;var&lt;/span&gt; builder = WebApplication.CreateBuilder(args);

&lt;span style=&quot;color: #64748b;&quot;&gt;// DbContextの登録&lt;/span&gt;
builder.Services.AddDbContext&amp;lt;AppDbContext&amp;gt;(options =&amp;gt;
    options.UseSqlServer(builder.Configuration.GetConnectionString(&lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;DefaultConnection&quot;&lt;/span&gt;)));

&lt;span style=&quot;color: #f472b6;&quot;&gt;var&lt;/span&gt; app = builder.Build();

&lt;span style=&quot;color: #64748b;&quot;&gt;// ★コンテナ起動時にデータベースを自動マイグレーション＆シード&lt;/span&gt;
&lt;span style=&quot;color: #f472b6;&quot;&gt;using&lt;/span&gt; (&lt;span style=&quot;color: #f472b6;&quot;&gt;var&lt;/span&gt; scope = app.Services.CreateScope())
{
    &lt;span style=&quot;color: #f472b6;&quot;&gt;var&lt;/span&gt; services = scope.ServiceProvider;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;try&lt;/span&gt;
    {
        &lt;span style=&quot;color: #f472b6;&quot;&gt;var&lt;/span&gt; context = services.GetRequiredService&amp;lt;AppDbContext&amp;gt;();
        &lt;span style=&quot;color: #64748b;&quot;&gt;// 未適用のマイグレーションがあれば自動適用（テーブル自動生成）&lt;/span&gt;
        &lt;span style=&quot;color: #f472b6;&quot;&gt;await&lt;/span&gt; context.Database.MigrateAsync();
        &lt;span style=&quot;color: #64748b;&quot;&gt;// 必要に応じて開発用テストデータをシード&lt;/span&gt;
        &lt;span style=&quot;color: #f472b6;&quot;&gt;await&lt;/span&gt; DbInitializer.SeedDataAsync(context);
    }
    &lt;span style=&quot;color: #f472b6;&quot;&gt;catch&lt;/span&gt; (Exception ex)
    {
        &lt;span style=&quot;color: #f472b6;&quot;&gt;var&lt;/span&gt; logger = services.GetRequiredService&amp;lt;ILogger&amp;lt;Program&amp;gt;&amp;gt;();
        logger.LogError(ex, &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;データベースのマイグレーション中にエラーが発生しました。&quot;&lt;/span&gt;);
        &lt;span style=&quot;color: #f472b6;&quot;&gt;throw&lt;/span&gt;;
    }
}

app.MapGet(&lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;/api/products&quot;&lt;/span&gt;, &lt;span style=&quot;color: #f472b6;&quot;&gt;async&lt;/span&gt; (AppDbContext db) =&amp;gt; &lt;span style=&quot;color: #f472b6;&quot;&gt;await&lt;/span&gt; db.Products.ToListAsync());

app.Run();
&lt;/pre&gt;
        &lt;/div&gt;

        &lt;h3 style=&quot;font-size: 18px; color: #0f172a; margin-top: 24px;&quot;&gt;HasData によるマスターデータのコード化&lt;/h3&gt;
        &lt;p&gt;
            EF Coreの &lt;code&gt;modelBuilder.Entity&amp;lt;T&amp;gt;().HasData(...)&lt;/code&gt; を使用すると、初期マスタデータ（例: 都道府県マスタ、権限ロール、ステータス定義）をC#コードとして完全にGit管理できます：
        &lt;/p&gt;

        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 16px 0; overflow-x: auto;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #64748b;&quot;&gt;// AppDbContext.cs&lt;/span&gt;
&lt;span style=&quot;color: #f472b6;&quot;&gt;public class&lt;/span&gt; &lt;span style=&quot;color: #38bdf8;&quot;&gt;AppDbContext&lt;/span&gt; : DbContext
{
    &lt;span style=&quot;color: #f472b6;&quot;&gt;public&lt;/span&gt; DbSet&amp;lt;Role&amp;gt; Roles { &lt;span style=&quot;color: #f472b6;&quot;&gt;get&lt;/span&gt;; &lt;span style=&quot;color: #f472b6;&quot;&gt;set&lt;/span&gt;; }
    &lt;span style=&quot;color: #f472b6;&quot;&gt;public&lt;/span&gt; DbSet&amp;lt;Product&amp;gt; Products { &lt;span style=&quot;color: #f472b6;&quot;&gt;get&lt;/span&gt;; &lt;span style=&quot;color: #f472b6;&quot;&gt;set&lt;/span&gt;; }

    &lt;span style=&quot;color: #f472b6;&quot;&gt;protected override void&lt;/span&gt; &lt;span style=&quot;color: #38bdf8;&quot;&gt;OnModelCreating&lt;/span&gt;(ModelBuilder modelBuilder)
    {
        &lt;span style=&quot;color: #f472b6;&quot;&gt;base&lt;/span&gt;.OnModelCreating(modelBuilder);

        &lt;span style=&quot;color: #64748b;&quot;&gt;// 必須マスタデータをMigrationファイル内に生成&lt;/span&gt;
        modelBuilder.Entity&amp;lt;Role&amp;gt;().HasData(
            &lt;span style=&quot;color: #f472b6;&quot;&gt;new&lt;/span&gt; Role { Id = 1, Name = &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;Administrator&quot;&lt;/span&gt; },
            &lt;span style=&quot;color: #f472b6;&quot;&gt;new&lt;/span&gt; Role { Id = 2, Name = &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;Member&quot;&lt;/span&gt; },
            &lt;span style=&quot;color: #f472b6;&quot;&gt;new&lt;/span&gt; Role { Id = 3, Name = &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;Guest&quot;&lt;/span&gt; }
        );
    }
}
&lt;/pre&gt;
        &lt;/div&gt;

        &lt;div style=&quot;background: #f0fdf4; border-left: 6px solid #16a34a; border-radius: 6px; padding: 16px 18px; margin: 20px 0;&quot;&gt;
            &lt;h4 style=&quot;margin: 0 0 6px 0; color: #15803d; font-size: 15.5px;&quot;&gt;💡 現場の使い分け黄金ルール&lt;/h4&gt;
            &lt;p style=&quot;margin: 0; font-size: 14.5px; line-height: 1.7; color: #166534;&quot;&gt;
                &lt;strong&gt;① システム必須の小規模マスタデータ（権限・区分値）:&lt;/strong&gt; EF Core の &lt;code&gt;HasData()&lt;/code&gt; でMigrationコードとしてGit管理。&lt;br/&gt;
                &lt;strong&gt;② 開発・ローカルテスト用の大量ダミーデータ（1万件の注文履歴など）:&lt;/strong&gt; &lt;code&gt;init.sql&lt;/code&gt; や独立したSeederスクリプトで管理し、本番マイグレーションを汚さない！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 第4章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第4章: チーム開発におけるゼロセットアップDBの Docker Compose 実践構成&lt;/h2&gt;
        &lt;p&gt;
            それでは、実際に現場でそのまま導入できる &lt;strong&gt;「ゼロセットアップDB環境」の完全なリポジトリ構造と設定ファイル&lt;/strong&gt; を見ていきましょう。
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_31_05_csharp_zero_setup_db.png&quot; alt=&quot;C#現場のゼロセットアップDB環境&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】新人が5分で開発開始！Docker ComposeによるゼロセットアップDB環境&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;h3 style=&quot;font-size: 18px; color: #0f172a; margin-top: 24px;&quot;&gt;推奨ディレクトリ構造&lt;/h3&gt;
        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 16px 0;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;my-csharp-project/
├── .env.example              &lt;span style=&quot;color: #64748b;&quot;&gt;# パスワード設定のテンプレート（Git共有）&lt;/span&gt;
├── .gitignore                 &lt;span style=&quot;color: #64748b;&quot;&gt;# .env や *.mdf を完全ブロック&lt;/span&gt;
├── docker-compose.yml         &lt;span style=&quot;color: #64748b;&quot;&gt;# サービス定義（WebAPI, DB, 初期化設定）&lt;/span&gt;
├── db-init/                   &lt;span style=&quot;color: #64748b;&quot;&gt;# 初期データ用SQLスクリプト配置フォルダ&lt;/span&gt;
│   ├── 01_create_schema.sql  &lt;span style=&quot;color: #64748b;&quot;&gt;# テーブル生成DDL（EF Core不使用時）&lt;/span&gt;
│   └── 02_seed_test_data.sql &lt;span style=&quot;color: #64748b;&quot;&gt;# テスト用顧客・商品レコードINSERT&lt;/span&gt;
└── src/
    └── MyWebApi/
        ├── Dockerfile
        ├── Program.cs
        └── appsettings.json
&lt;/pre&gt;
        &lt;/div&gt;

        &lt;h3 style=&quot;font-size: 18px; color: #0f172a; margin-top: 24px;&quot;&gt;PostgreSQLを採用した場合の超シンプル Compose 例&lt;/h3&gt;
        &lt;p&gt;
            PostgreSQLを採用している場合、設定は驚くほどシンプルです。&lt;code&gt;./db-init&lt;/code&gt; フォルダを &lt;code&gt;/docker-entrypoint-initdb.d&lt;/code&gt; にマウントするだけで、初回起動時に自動実行されます：
        &lt;/p&gt;

        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 16px 0; overflow-x: auto;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #7dd3fc;&quot;&gt;services:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;webapi:&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;build:&lt;/span&gt; ./src/MyWebApi
    &lt;span style=&quot;color: #f472b6;&quot;&gt;ports:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;5000:5000&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;environment:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=shop_dev;Username=postgres;Password=${POSTGRES_PASSWORD}&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;depends_on:&lt;/span&gt;
      &lt;span style=&quot;color: #cbd5e1;&quot;&gt;db:&lt;/span&gt;
        &lt;span style=&quot;color: #cbd5e1;&quot;&gt;condition:&lt;/span&gt; service_healthy

  &lt;span style=&quot;color: #38bdf8;&quot;&gt;db:&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;image:&lt;/span&gt; postgres:16-alpine
    &lt;span style=&quot;color: #f472b6;&quot;&gt;environment:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;POSTGRES_DB=shop_dev&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;POSTGRES_PASSWORD=${POSTGRES_PASSWORD}&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;volumes:&lt;/span&gt;
      &lt;span style=&quot;color: #64748b;&quot;&gt;# 実データはNamed Volumeで永続保持&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;
      &lt;span style=&quot;color: #64748b;&quot;&gt;# ★初回起動時のみ実行される初期化SQLフォルダを読み取り専用マウント&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;./db-init:/docker-entrypoint-initdb.d:ro&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;healthcheck:&lt;/span&gt;
      &lt;span style=&quot;color: #f472b6;&quot;&gt;test:&lt;/span&gt; [&lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;CMD-SHELL&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;pg_isready -U postgres -d shop_dev&quot;&lt;/span&gt;]
      &lt;span style=&quot;color: #f472b6;&quot;&gt;interval:&lt;/span&gt; 3s
      &lt;span style=&quot;color: #f472b6;&quot;&gt;timeout:&lt;/span&gt; 3s
      &lt;span style=&quot;color: #f472b6;&quot;&gt;retries:&lt;/span&gt; 5

&lt;span style=&quot;color: #7dd3fc;&quot;&gt;volumes:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;postgres_data:&lt;/span&gt;
&lt;/pre&gt;
        &lt;/div&gt;

        &lt;p&gt;
            新人がプロジェクトに着任した初日、リポジトリを &lt;code&gt;git clone&lt;/code&gt; して &lt;code&gt;.env.example&lt;/code&gt; を &lt;code&gt;.env&lt;/code&gt; にコピーし、&lt;code&gt;docker compose up -d&lt;/code&gt; と打つだけで、数分後には完全なテスト環境がブラウザやSwaggerで動作します。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第5章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第5章: 現場トラブルシューティング＆ベストプラクティス&lt;/h2&gt;
        &lt;p&gt;
            初期データ自動投入を運用する中で、チームが必ず遭遇する &lt;strong&gt;「3大ハマりポイント」とその即効解決策&lt;/strong&gt; を解説します。
        &lt;/p&gt;

        &lt;div style=&quot;background: #fff1f2; border-left: 6px solid #e11d48; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
            &lt;h4 style=&quot;margin: 0 0 8px 0; color: #be123c; font-size: 16px;&quot;&gt;🚨 トラブル①: 「init.sql を書き換えたのに、コンテナを再起動しても反映されない！」&lt;/h4&gt;
            &lt;p style=&quot;margin: 0; font-size: 14.5px; line-height: 1.8; color: #4c0519;&quot;&gt;
                &lt;strong&gt;【原因】:&lt;/strong&gt; &lt;code&gt;entrypoint-initdb.d&lt;/code&gt; は &lt;strong&gt;「Volumeが空の初回起動時のみ」&lt;/strong&gt; 実行されます。既にNamed VolumeにDBデータが作成されている場合、2回目以降の起動では完全にスキップされます。&lt;br/&gt;
                &lt;strong&gt;【解決策】:&lt;/strong&gt; Volumeを破棄して再作成します：&lt;br/&gt;
                &lt;code&gt;docker compose down -v&lt;/code&gt;&lt;br/&gt;
                &lt;code&gt;docker compose up -d&lt;/code&gt;&lt;br/&gt;
                &lt;code&gt;-v&lt;/code&gt; オプションを付けることで古いVolumeが削除され、初期化スクリプトが再び実行されます。
            &lt;/p&gt;
        &lt;/div&gt;

        &lt;div style=&quot;background: #fff7ed; border-left: 6px solid #f97316; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
            &lt;h4 style=&quot;margin: 0 0 8px 0; color: #c2410c; font-size: 16px;&quot;&gt;🚨 トラブル②: 「複数のSQLファイルの実行順序がバラバラで外部キー制約エラーになる！」&lt;/h4&gt;
            &lt;p style=&quot;margin: 0; font-size: 14.5px; line-height: 1.8; color: #7c2d12;&quot;&gt;
                &lt;strong&gt;【原因】:&lt;/strong&gt; &lt;code&gt;entrypoint-initdb.d&lt;/code&gt; はファイルを辞書順（アルファベット順）に実行します。&lt;code&gt;schema.sql&lt;/code&gt; より先に &lt;code&gt;seed.sql&lt;/code&gt; が呼ばれるとテーブル未作成エラーになります。&lt;br/&gt;
                &lt;strong&gt;【解決策】:&lt;/strong&gt; ファイル名の先頭に必ず &lt;code&gt;01_&lt;/code&gt;, &lt;code&gt;02_&lt;/code&gt; のような連番プレフィックスを付与します：&lt;br/&gt;
                &lt;code&gt;01_create_tables.sql&lt;/code&gt; ➡ &lt;code&gt;02_seed_master.sql&lt;/code&gt; ➡ &lt;code&gt;03_seed_test_orders.sql&lt;/code&gt;
            &lt;/p&gt;
        &lt;/div&gt;

        &lt;div style=&quot;background: #f0f9ff; border-left: 6px solid #0284c7; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
            &lt;h4 style=&quot;margin: 0 0 8px 0; color: #0369a1; font-size: 16px;&quot;&gt;🚨 トラブル③: 「本番環境でも Database.Migrate() を起動時に実行していいの？」&lt;/h4&gt;
            &lt;p style=&quot;margin: 0; font-size: 14.5px; line-height: 1.8; color: #0c4a6e;&quot;&gt;
                &lt;strong&gt;【現場プラクティス】:&lt;/strong&gt; 単一インスタンスのローカル開発や検証環境では非常に便利ですが、&lt;strong&gt;本番環境で複数インスタンス（KubernetesやECS等）が同時にスケール起動する場合、マイグレーション競合やデッドロックのリスク&lt;/strong&gt; があります。&lt;br/&gt;
                本番環境では、CI/CDパイプライン（GitHub Actionsなど）のデプロイステップで &lt;code&gt;dotnet ef database update&lt;/code&gt; を単独実行するか、専用のマイグレーションJobを実行するのがエンタープライズの標準手法です。
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 第6章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第6章: 第6部総まとめと理解度チェッククイズ&lt;/h2&gt;
        &lt;p&gt;
            これで第6部「データの永続化とボリューム（Volume &amp; Bind Mount）」の全カリキュラム（Day 27〜31）がすべて完了しました！&lt;br/&gt;
            コンテナの基本原則であるステートレス設計から、Named Volumeによる堅牢なデータ保持、Bind Mountによる爆速開発、GitとVolumeの境界線ルール、そして今回のゼロセットアップDB環境の構築まで、&lt;strong&gt;「データ永続化と開発スピードを完璧に両立させるプロフェッショナルの技術」&lt;/strong&gt; を完全にマスターしました！
        &lt;/p&gt;

        &lt;!-- 理解度チェッククイズ --&gt;
        &lt;div style=&quot;background: linear-gradient(135deg, #f0fdf4 0%, #e0f2fe 100%); border: 1px solid #86efac; border-radius: 8px; padding: 22px 24px; margin: 30px 0;&quot;&gt;
            &lt;h3 style=&quot;color: #166534; margin-top: 0; margin-bottom: 14px; font-size: 18px; display: flex; align-items: center;&quot;&gt;
                &lt;span style=&quot;font-size: 22px; margin-right: 8px;&quot;&gt;🎯&lt;/span&gt;
                理解度チェッククイズ！
            &lt;/h3&gt;
            &lt;p style=&quot;font-size: 15px; color: #1e293b; margin-bottom: 14px;&quot;&gt;
                &lt;strong&gt;問:&lt;/strong&gt; 開発チームのメンバーが「初期投入用スクリプト（init.sql）にテストユーザーを追加したのですが、&lt;code&gt;docker compose restart&lt;/code&gt; を実行してもデータベースに反映されません」と困っています。理由と正しい反映手順を説明してください。
            &lt;/p&gt;
            &lt;details style=&quot;background: #ffffff; padding: 14px 18px; border-radius: 6px; border: 1px solid #bbf7d0; cursor: pointer;&quot;&gt;
                &lt;summary style=&quot;font-weight: bold; color: #0284c7;&quot;&gt;正解と解説を確認する&lt;/summary&gt;
                &lt;div style=&quot;margin-top: 12px; font-size: 14.5px; line-height: 1.8; color: #334155;&quot;&gt;
                    &lt;p style=&quot;margin: 0 0 8px 0; color: #e11d48; font-weight: bold;&quot;&gt;【正解と解説】&lt;/p&gt;
                    &lt;p style=&quot;margin: 0 0 8px 0;&quot;&gt;
                        &lt;strong&gt;理由:&lt;/strong&gt; データベースコンテナの &lt;code&gt;entrypoint-initdb.d&lt;/code&gt; 機構は、データディレクトリ（Volume）が空である「初回起動時のみ」動作する安全設計になっているためです。再起動（&lt;code&gt;restart&lt;/code&gt;）では既にデータが存在するため、スクリプトの実行はスキップされます。
                    &lt;/p&gt;
                    &lt;p style=&quot;margin: 0;&quot;&gt;
                        &lt;strong&gt;正しい反映手順:&lt;/strong&gt;&lt;br/&gt;
                        ① &lt;code&gt;docker compose down -v&lt;/code&gt; を実行して既存のNamed Volumeを削除する。&lt;br/&gt;
                        ② &lt;code&gt;docker compose up -d&lt;/code&gt; を実行して空のVolumeで再起動し、更新された &lt;code&gt;init.sql&lt;/code&gt; を自動実行させる。
                    &lt;/p&gt;
                &lt;/div&gt;
            &lt;/details&gt;
        &lt;/div&gt;

        &lt;!-- 次回予告 --&gt;
        &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 20px 24px; margin: 30px 0; border: 1px solid #cbd5e1;&quot;&gt;
            &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 10px; font-size: 17px;&quot;&gt;🚀 次回予告：第7部「Dockerネットワークの基礎とサービス間通信」開幕！&lt;/h3&gt;
            &lt;p style=&quot;margin: 0; font-size: 15px; line-height: 1.8; color: #334155;&quot;&gt;
                次回Day 32からは、いよいよ待望の &lt;strong&gt;第7部「Dockerネットワーク」&lt;/strong&gt; に突入します！&lt;br/&gt;
                「なぜ &lt;code&gt;docker-compose.yml&lt;/code&gt; の中では &lt;code&gt;localhost&lt;/code&gt; ではなくサービス名（&lt;code&gt;db&lt;/code&gt;）で通信できるのか？」&lt;br/&gt;
                Docker内部に自動生成される仮想ブリッジネットワーク（Bridge Network）や組み込みDNSサーバーの驚くべき仕組みを徹底的に解き明かします。ご期待ください！
            &lt;/p&gt;
        &lt;/div&gt;

    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/186052056046118328/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-31-db-entrypoint-initdb-c-ef-core-db.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/186052056046118328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/186052056046118328'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-31-db-entrypoint-initdb-c-ef-core-db.html' title='【Day 31】データベース初期データ（シードデータ）の自動投入テクニック 〜新人の手動DBリストアを完全撤廃！ entrypoint-initdb の仕組み、C# EF Core 起動時マイグレーション、ゼロセットアップDB環境の構築〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/133ccBazLc71bAsA6sWpD_owCRuQaZjV2=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-7496801857772230531</id><published>2026-10-26T18:13:29.070+09:00</published><updated>2026-10-26T18:13:29.070+09:00</updated><title type='text'>【Day 28】git add -p で必要な行だけを綺麗にコミットする部分ステージング技</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1vm57xx5lG_5YIzwC4zKbpXpG6owHdJ7E&quot; alt=&quot;Day 28 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 28】git add -p で必要な行だけを綺麗にコミットする部分ステージング技&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 27では、巨大なC#ソリューションでの再ビルド待ちを完全ゼロにする神機能&lt;strong&gt;「git worktree」&lt;/strong&gt;の内部構造と2画面並行デバッグの極意を学びました。&lt;br/&gt;
            そして本日のDay 28は、プロの現場で毎日のように使われる超実践テクニック——&lt;strong&gt;【git add -p で必要な行だけを綺麗にコミットする部分ステージング技】&lt;/strong&gt;を徹底解説します！&lt;br/&gt;
            「C#のバグ調査や新機能開発の際、変数の値を確認するためにコードの途中に &lt;code&gt;Console.WriteLine&lt;/code&gt; を差し込んだり、一時的なハードコード（テスト用の固定値やフラグ）を書き込むことはよくありますよね」&lt;br/&gt;
            「しかし、いざコミットしようとしたとき、そのデバッグ行を手動で1行ずつ削除したりコメントアウトして、再度ビルド確認してからコミットしていませんか？ あるいは、削除し忘れたデバッグログがそのまま本番リポジトリにコミットされ、Pull Requestのレビューで『不要なデバッグ出力が残っていますよ』と指摘されて恥ずかしい思いをしたことはありませんか？」&lt;br/&gt;
            かつてのSubversion (SVN) では「ファイル単位」でしかコミット対象を選択できなかったため、そうした苦労は避けられませんでした。&lt;br/&gt;
            しかしGitには、&lt;strong&gt;1つのファイル内にある変更箇所を行単位（Hunk：ハンク）で自由自在に選別し、必要な行だけをインデックス（ステージング）に載せる『git add -p (patch)』&lt;/strong&gt;という強力無比な機能が備わっています！&lt;br/&gt;
            ローカルのデバッグ用ログを残したまま、本番用修正コードだけを100%美しくコミットするプロの極意を、コマンドラインとTortoiseGit GUIの両面から完全マスターしましょう！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        現場で優れたエンジニアと評価される基準の1つに、「コミット履歴の美しさ（Atomic Commit：単一責務のコミット）」があります。&lt;br/&gt;
        1つのコミットに「本番のバグ修正」と「関係のない一時デバッグコード」や「ついでに行った別機能のリファクタリング」がごちゃ混ぜになっていると、コードレビューの負担が跳ね上がり、将来障害が発生して &lt;code&gt;git revert&lt;/code&gt; や &lt;code&gt;git bisect&lt;/code&gt; を行う際にも大きな事故の原因になります。&lt;br/&gt;
        本日は、1つのファイルから必要な行だけをピンポイントで切り出して美しいコミットを仕立てるプロの技術を習得します。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;SVNのファイル丸ごとコミットとGitの行単位部分ステージング（Hunk管理）の決定的違いを理解する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git add -p&lt;/code&gt;（パッチモード）の対話プロンプトと主要操作コマンド（&lt;code&gt;y&lt;/code&gt;, &lt;code&gt;n&lt;/code&gt;, &lt;code&gt;s&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;, &lt;code&gt;q&lt;/code&gt;）を完全習得する&lt;/li&gt;
            &lt;li&gt;C#クラス内で発生する「本番修正ロジック」と「デバッグ用Console.WriteLine / 一時フラグ」を行単位で峻別する実践フローを身につける&lt;/li&gt;
            &lt;li&gt;変更ブロックが隣接している場合に &lt;code&gt;s&lt;/code&gt; (Split) や &lt;code&gt;e&lt;/code&gt; (Edit) を駆使して極限まで細かく選別する技をマスターする&lt;/li&gt;
            &lt;li&gt;TortoiseGit（TortoiseGitMerge）のGUIを活用し、マウス右クリックで行単位ステージング・破棄を行う直感的手順を習得する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git diff --cached&lt;/code&gt; でコミット直前のステージング状態を100%安全に確認するプロの検証ルーティンを確立する&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: ファイル丸ごとコミットの悲劇 vs 部分ステージング --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】従来のファイル丸ごとコミットの悲劇 vs git add -p による部分ステージング&lt;/h2&gt;
    &lt;p&gt;
        まず、従来のSubversion (SVN) や初心者が陥りがちな「ファイル丸ごとコミット」の落とし穴と、Gitの部分ステージングによる解決策を図解で対比してみましょう。
    &lt;/p&gt;

    &lt;!-- 図解① --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1bSj5wuHQv3bU1EUes0caehpqhJbEnAba&quot; alt=&quot;ファイル丸ごとコミットの悲劇 vs git add -p による部分ステージング&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】従来のファイル丸ごとコミット（デバッグログ本番混入の悲劇） vs git add -p（行単位選別で美しいコミット）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        Subversionでは、コミットの最小単位が「ファイル」でした。そのため、1つのファイルの中で作業していると、次のようなジレンマに直面していました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #fff1f2; border-left: 5px solid #e11d48; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #be123c; font-size: 16.5px;&quot;&gt;💥 SVN時代・ファイル丸ごとコミットの3大悲劇&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85; color: #4c0519;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;デバッグコードの誤コミット:&lt;/strong&gt; 調査のために入れた &lt;code&gt;Console.WriteLine(&quot;DEBUG: user count=&quot; + count);&lt;/code&gt; や、テスト用にコメントアウトした認証処理を戻し忘れ、本番コードに混入してしまう。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;手動削除による再デバッグの困難:&lt;/strong&gt; コミット前にデバッグコードをわざわざ手で消し、もし後から再度バグ調査が必要になったら、また同じデバッグコードをゼロから打ち直すという二度手間が発生する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;無関係な変更の混入（Dirty Commit）:&lt;/strong&gt; 本番バグを直している最中に、気になったコードのインデントを直したり関係ないコメントを追記してしまい、1つのコミットに関心の異なる変更が混在してレビューが難航する。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        これに対してGitは、&lt;strong&gt;「ワーキングツリー（ローカル作業フォルダ）」と「インデックス（ステージング領域）」が完全に分離&lt;/strong&gt;されています。&lt;br/&gt;
        この構造のおかげで、&lt;strong&gt;「ローカルファイル上にはデバッグログや一時的な実験コードを残したまま、本番にコミットしたい行だけをインデックスにコピーする」&lt;/strong&gt;という魔法のような芸当が可能になります。それをCLIで対話的に実行するコマンドが &lt;code&gt;git add -p&lt;/code&gt;（または &lt;code&gt;git add --patch&lt;/code&gt;）です！
    &lt;/p&gt;

    &lt;!-- セクション③: 対話モードとHunk操作コマンド --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】git add -p の対話モードとHunk操作コマンド完全図解&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;git add -p&lt;/code&gt; を実行すると、Gitはファイル内の差分をひとかたまりの変更ブロック（&lt;strong&gt;Hunk：ハンク&lt;/strong&gt;）ごとに切り分けて画面に表示し、対話プロンプトで「このブロックをステージングしますか？」と尋ねてきます。
    &lt;/p&gt;

    &lt;!-- 図解② --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1EL6mCb-hCvJYvOuyYYCNiEJuDkayKgLY&quot; alt=&quot;git add -p の対話モードとHunk操作コマンド完全図解&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】対話プロンプトと主要操作コマンド（y: 採用 / n: スキップ / s: 分割 / e: 手動編集 / q: 中断）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        対話プロンプトに表示される &lt;code&gt;Stage this hunk [y,n,q,a,d,s,e,?]?&lt;/code&gt; の各コマンドの意味を完璧に整理しておきましょう。
    &lt;/p&gt;

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #3b82f6; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #1d4ed8; font-size: 16.5px;&quot;&gt;📋 Hunk操作コマンドの決定版チートシート&lt;/strong&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 15px; color: #1e293b;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #dbeafe; border-bottom: 2px solid #93c5fd;&quot;&gt;
                    &lt;th style=&quot;padding: 10px; text-align: center; width: 12%;&quot;&gt;キー&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 28%;&quot;&gt;名称&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; width: 60%;&quot;&gt;動作と実務での活用法&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0; background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; text-align: center; font-weight: bold; color: #16a34a; font-size: 18px;&quot;&gt;y&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;yes（ステージング）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;表示されているHunkをステージング領域に追加します。本番修正コードのブロックで押します。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0; background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; text-align: center; font-weight: bold; color: #dc2626; font-size: 18px;&quot;&gt;n&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;no（スキップ）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;このHunkをステージングせずスキップします。作業フォルダのファイルは変更されずそのまま残ります（デバッグログ等）。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0; background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; text-align: center; font-weight: bold; color: #0284c7; font-size: 18px;&quot;&gt;s&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;split（さらに分割）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;表示中のHunkの中に「本番修正」と「デバッグログ」が両方含まれている場合、間に未変更行があれば2つ以上の小さなHunkに自動分割します。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0; background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; text-align: center; font-weight: bold; color: #9333ea; font-size: 18px;&quot;&gt;e&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;edit（手動編集）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;変更行が直結していて &lt;code&gt;s&lt;/code&gt; で自動分割できない場合、エディタを開いて不要な &lt;code&gt;+&lt;/code&gt; 行を削除し、手動でパッチを微調整します。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0; background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; text-align: center; font-weight: bold; color: #475569; font-size: 18px;&quot;&gt;q&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;quit（中断・終了）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;途中でステージング処理を終了します。それまでに &lt;code&gt;y&lt;/code&gt; を押したHunkはステージングされた状態で保持されます。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; text-align: center; font-weight: bold; color: #64748b; font-size: 18px;&quot;&gt;?&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;help（ヘルプ）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px;&quot;&gt;使用可能な全コマンドの簡単な説明を表示します。&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- セクション④: C#現場での実践フロー --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【図解】C#現場での実践！デバッグ用Console.WriteLine混入防止フロー&lt;/h2&gt;
    &lt;p&gt;
        それでは、実際のC#開発現場を想定した具体的なシナリオで &lt;code&gt;git add -p&lt;/code&gt; の実践手順を見てみましょう！
    &lt;/p&gt;

    &lt;!-- 図解③ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1N50J5_YjR2UgzmTGxkKkuYhlmq7iM4EC&quot; alt=&quot;C#現場での実践！デバッグ用Console.WriteLine混入防止フロー&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】C#クラス（OrderService.cs）の本番修正とデバッグログを行単位で切り離す実戦フロー&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 25px;&quot;&gt;💻 実例：OrderService.cs のバグ修正シナリオ&lt;/h3&gt;
    &lt;p&gt;
        ECサイトの注文処理サービス &lt;code&gt;OrderService.cs&lt;/code&gt; において、「割引額が負数になった場合に例外をスローする」というバグ修正を行いました。&lt;br/&gt;
        しかし開発中、動作確認のために途中で &lt;code&gt;Console.WriteLine&lt;/code&gt; による値の出力や、一時的なフラグ変数を書き加えています。
    &lt;/p&gt;

    &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; line-height: 1.6; overflow-x: auto; margin: 20px 0;&quot;&gt;
&lt;span style=&quot;color: #94a3b8;&quot;&gt;// OrderService.cs の現在の作業フォルダ内の状態&lt;/span&gt;
public decimal CalculateFinalPrice(Order order, decimal discount)
{
&lt;span style=&quot;color: #f87171;&quot;&gt;+   // 一時デバッグ用: 渡ってきた注文IDと割引額をログ出力（本番不要！）&lt;/span&gt;
&lt;span style=&quot;color: #f87171;&quot;&gt;+   Console.WriteLine($&quot;[DEBUG] Calculating discount for Order: {order.Id}, discount: {discount}&quot;);&lt;/span&gt;

&lt;span style=&quot;color: #4ade80;&quot;&gt;+   // ★ 本番修正コード: 負数の割引を弾くバリデーションガード&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+   if (discount &amp;lt; 0)&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+   {&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+       throw new ArgumentOutOfRangeException(nameof(discount), &quot;割引額を負数にすることはできません。&quot;);&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+   }&lt;/span&gt;

    decimal total = order.SubTotal - discount;
    return total &amp;gt; 0 ? total : 0;
}
    &lt;/div&gt;

    &lt;p&gt;
        ここで &lt;code&gt;git add OrderService.cs&lt;/code&gt; や &lt;code&gt;git commit -am &quot;fix&quot;&lt;/code&gt; を実行してしまうと、赤色の一時デバッグログまで本番に混入してしまいます。&lt;br/&gt;
        そこで、ターミナルで &lt;code&gt;git add -p OrderService.cs&lt;/code&gt; を実行します！
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #e2e8f0; padding: 18px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14px; line-height: 1.6; overflow-x: auto; margin: 20px 0;&quot;&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;$ git add -p OrderService.cs&lt;/span&gt;
diff --git a/OrderService.cs b/OrderService.cs
index a1b2c3d..e4f5g6h 100644
--- a/OrderService.cs
+++ b/OrderService.cs
@@ -10,6 +10,14 @@ public decimal CalculateFinalPrice(Order order, decimal discount)
&lt;span style=&quot;color: #f87171;&quot;&gt;+   Console.WriteLine($&quot;[DEBUG] Calculating discount for Order: {order.Id}, discount: {discount}&quot;);&lt;/span&gt;
+
&lt;span style=&quot;color: #4ade80;&quot;&gt;+   if (discount &amp;lt; 0)&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+   {&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+       throw new ArgumentOutOfRangeException(nameof(discount), &quot;割引額を負数にすることはできません。&quot;);&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+   }&lt;/span&gt;
     decimal total = order.SubTotal - discount;
&lt;span style=&quot;color: #facc15;&quot;&gt;Stage this hunk [y,n,q,a,d,s,e,?]?&lt;/span&gt; &lt;span style=&quot;color: #ffffff; font-weight: bold;&quot;&gt;s&lt;/span&gt;   &lt;span style=&quot;color: #94a3b8;&quot;&gt;← ここで s (Split) を入力して分割！&lt;/span&gt;

Split into 2 hunks.
@@ -10,2 +10,4 @@ public decimal CalculateFinalPrice(Order order, decimal discount)
&lt;span style=&quot;color: #f87171;&quot;&gt;+   Console.WriteLine($&quot;[DEBUG] Calculating discount for Order: {order.Id}, discount: {discount}&quot;);&lt;/span&gt;
&lt;span style=&quot;color: #facc15;&quot;&gt;Stage this hunk [y,n,q,a,d,s,e,?]?&lt;/span&gt; &lt;span style=&quot;color: #ffffff; font-weight: bold;&quot;&gt;n&lt;/span&gt;   &lt;span style=&quot;color: #94a3b8;&quot;&gt;← デバッグログなので n (No) で除外！&lt;/span&gt;

@@ -12,6 +14,6 @@ public decimal CalculateFinalPrice(Order order, decimal discount)
&lt;span style=&quot;color: #4ade80;&quot;&gt;+   if (discount &amp;lt; 0)&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+   {&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+       throw new ArgumentOutOfRangeException(nameof(discount), &quot;割引額を負数にすることはできません。&quot;);&lt;/span&gt;
&lt;span style=&quot;color: #4ade80;&quot;&gt;+   }&lt;/span&gt;
&lt;span style=&quot;color: #facc15;&quot;&gt;Stage this hunk [y,n,q,a,d,s,e,?]?&lt;/span&gt; &lt;span style=&quot;color: #ffffff; font-weight: bold;&quot;&gt;y&lt;/span&gt;   &lt;span style=&quot;color: #94a3b8;&quot;&gt;← 本番修正なので y (Yes) でステージング！&lt;/span&gt;
    &lt;/div&gt;

    &lt;p&gt;
        たったこれだけです！&lt;br/&gt;
        これでインデックス（ステージング）にはバグ修正コードだけが登録され、作業フォルダには引き続き &lt;code&gt;Console.WriteLine&lt;/code&gt; が残ったままになります。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f0fdf4; border-left: 5px solid #22c55e; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #15803d; font-size: 16.5px;&quot;&gt;🔍 プロの必須習慣：コミット直前に git diff --cached を叩け！&lt;/strong&gt;
        &lt;p style=&quot;margin: 8px 0 0 0; line-height: 1.8; color: #166534;&quot;&gt;
            ステージングを終えたら、いきなりコミットするのではなく、必ず次のコマンドを実行しましょう：&lt;br/&gt;
            &lt;code&gt;&lt;strong&gt;git diff --cached&lt;/strong&gt;&lt;/code&gt;（または &lt;code&gt;git diff --staged&lt;/code&gt;）&lt;br/&gt;
            通常の &lt;code&gt;git diff&lt;/code&gt; は「作業フォルダとステージングの差分」を表示しますが、&lt;code&gt;--cached&lt;/code&gt; オプションを付けると&lt;strong&gt;「ステージング領域と前回のコミットの差分（＝今からコミットされる純粋な内容）」&lt;/strong&gt;だけが表示されます。&lt;br/&gt;
            ここで余計なデバッグ行や一時コードが含まれていないことを100%確認してから &lt;code&gt;git commit -m &quot;fix: ...&quot;&lt;/code&gt; を実行するのが、プロエンジニアの鉄則です。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑤: TortoiseGitでの視覚的GUI操作 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【図解】TortoiseGitで行単位・ブロック単位にステージングする視覚的GUI操作&lt;/h2&gt;
    &lt;p&gt;
        「黒い画面（CLI）での対話モードはちょっと敷居が高い……」「左右のカラー差分を見比べながらマウスで安全に選びたい」というWindowsエンジニアの方も安心してください。&lt;br/&gt;
        エクスプローラー統合の定番GUIツール &lt;strong&gt;TortoiseGit&lt;/strong&gt; を使えば、マウス操作だけでまったく同じ部分ステージングが可能です！
    &lt;/p&gt;

    &lt;!-- 図解④ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1x4S4n00Rjwa4DQSX2WTqftlwqR1MsDLI&quot; alt=&quot;TortoiseGitで行単位・ブロック単位にステージングする視覚的GUI操作&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】Windowsエクスプローラー＆TortoiseGitMergeを活用した直感的マウス操作による部分ステージング&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px; margin: 20px 0;&quot;&gt;
        &lt;strong style=&quot;color: #0f172a; font-size: 17px;&quot;&gt;🖱️ TortoiseGitでの行単位ステージング 4ステップ手順&lt;/strong&gt;
        &lt;ol style=&quot;margin: 12px 0 0 0; padding-left: 22px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;コミットダイアログを開く:&lt;/strong&gt; プロジェクトフォルダを右クリックし、「Git コミット(C) -&amp;gt; &quot;ブランチ名&quot;...」を選択します。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;差分比較（TortoiseGitMerge）を起動:&lt;/strong&gt; 変更されたC#ファイルをリストからダブルクリックします。左右に差分が表示されたTortoiseGitMergeウィンドウが開きます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;除外したい行・ブロックを選択して右クリック:&lt;/strong&gt;
                &lt;ul style=&quot;margin: 6px 0; padding-left: 18px;&quot;&gt;
                    &lt;li&gt;&lt;strong&gt;変更を破棄して完全に元に戻したい場合:&lt;/strong&gt; 該当ブロックを右クリックして「このブロックの変更を取り消す」を選択。&lt;/li&gt;
                    &lt;li&gt;&lt;strong&gt;作業フォルダに残したままコミット対象から外す場合:&lt;/strong&gt; コミットダイアログ側の「ステージングを使用」機能（またはパッチ作成）を有効にし、コミット対象とするブロックだけを選択してステージングに移動。&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;コミットと確認:&lt;/strong&gt; コミットダイアログに戻ると、選択したブロックだけがステージング領域に反映されているため、メッセージを入力してコミットします。&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;!-- まとめセクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;📌 まとめ＆明日の予告&lt;/h2&gt;
    &lt;div style=&quot;background: #faf5ff; border-left: 5px solid #a855f7; padding: 18px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #7e22ce; font-size: 17px;&quot;&gt;🎓 本日の最重要チェックポイント&lt;/strong&gt;
        &lt;ul style=&quot;margin: 10px 0 0 0; padding-left: 20px; line-height: 1.85; color: #3b0764;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;SVNとの決定的差:&lt;/strong&gt; SVNのファイル丸ごとコミットと決別し、Gitのインデックス（ステージング）を活用して行単位（Hunk）で美しく選別コミットせよ！&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;対話モードの3種の神器:&lt;/strong&gt; &lt;code&gt;git add -p&lt;/code&gt; を実行し、&lt;code&gt;y&lt;/code&gt;（採用）、&lt;code&gt;n&lt;/code&gt;（除外・ローカル維持）、&lt;code&gt;s&lt;/code&gt;（細分化Split）を自在に使いこなせ！&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;コミット前の絶対防壁:&lt;/strong&gt; コミット前には必ず &lt;code&gt;git diff --cached&lt;/code&gt; を叩き、デバッグログや一時フラグが混入していないことを自分の目で100%確かめよ！&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p style=&quot;margin-top: 30px;&quot;&gt;
        次回&lt;strong&gt;【Day 29】&lt;/strong&gt;のテーマは、&lt;strong&gt;【git blame &amp; git log -L でC#コードの「犯人・導入理由」を完全特定】&lt;/strong&gt;です！&lt;br/&gt;
        「この怪しいif文は一体誰が何のために書いたのか？」「このC#メソッドの過去5年間の変更履歴をピンポイントで追跡したい！」という疑問を瞬時に解決するコード考古学の必須ツール &lt;code&gt;git blame&lt;/code&gt; と &lt;code&gt;git log -L&lt;/code&gt; の奥義を解説します。お楽しみに！
    &lt;/p&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/7496801857772230531/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-28git-add-p.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/7496801857772230531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/7496801857772230531'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-28git-add-p.html' title='【Day 28】git add -p で必要な行だけを綺麗にコミットする部分ステージング技'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1vm57xx5lG_5YIzwC4zKbpXpG6owHdJ7E=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-6896788009221641826</id><published>2026-10-26T09:20:37.827+09:00</published><updated>2026-10-26T09:20:37.827+09:00</updated><title type='text'>【Day 30】Git管理すべきファイルとVolumeに逃がすべきデータの境界線 〜コード（Git）・構成（Git/.env）・データ（Volume）の3層分離、巨大mdfバイナリ混入事故の防止、.gitignore徹底、チーム開発共有ルール〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1RUIF2YNYTmmwgKWrms3Wa6GeEU_olj9Z&quot; alt=&quot;Day 30 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 30: Git管理すべきファイルとVolumeに逃がすべきデータの境界線&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 導入メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: linear-gradient(135deg, #e0f2fe 0%, #f0fdf4 100%); border-left: 6px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0; box-shadow: 0 4px 12px rgba(13,183,237,0.08);&quot;&gt;
        &lt;div style=&quot;font-size: 32px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;font-size: 15.5px; color: #0f172a;&quot;&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; font-weight: bold; color: #0369a1; font-size: 17px;&quot;&gt;「Dockerプロジェクト内のファイル、何でもGitにコミットしていませんか？」&lt;/p&gt;
            &lt;p style=&quot;margin: 0; line-height: 1.8;&quot;&gt;
                前回のDay 29では、ホストPCとコンテナを直結してC#のホットリロードを実現する「バインドマウント（Bind Mount）」を学びました。&lt;br/&gt;
                コンテナ環境でのデータ永続化（Named Volume）と高速開発（Bind Mount）の両輪を手に入れた開発チームが、次に必ず直面するのが &lt;strong&gt;「プロジェクト内のどのファイルをGitで管理し、何をVolumeやローカルに逃がすべきか？」という境界線の問題&lt;/strong&gt; です。&lt;br/&gt;
                昔のオンプレミス現場では、ファイルサーバーの共有フォルダにソースコード、SQL Serverの &lt;code&gt;.mdf&lt;/code&gt; ファイル、設定ファイル、果てはログまで何でも放り込み、誰かが上書きしてDBが破損するなどの地獄絵図が日常茶飯事でした。&lt;br/&gt;
                もしこの悪習をそのまま現代のGit×Docker環境に持ち込み、&lt;strong&gt;巨大なデータベースファイルをGitにコミットしてしまうと、リポジトリが数十GBに膨れ上がり、チーム全員のPCでクローン不能になる壊滅的事故&lt;/strong&gt; を引き起こします。&lt;br/&gt;
                本講義は第6部「データの永続化とボリューム」の総決算として、&lt;strong&gt;「コード（Git）」「構成（Git/.env）」「データ（Volume）」の3層分離原則&lt;/strong&gt; と、事故を未然に防ぐ現場ルールを完全解説します！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 目次セクション --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 12px; font-size: 17px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 4px; padding: 2px 8px; font-size: 13px; margin-right: 10px;&quot;&gt;INDEX&lt;/span&gt;
            本日の講義カリキュラム
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #475569; font-size: 15px; line-height: 2;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;第1章: 共有フォルダ破綻の歴史に学ぶ 〜なぜ「何でも詰め込み」は失敗するのか？〜&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第2章: 現代コンテナ開発における「3層分離（コード・構成・データ）」の原則&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第3章: 現場向け「ファイル行き先判定マトリクス」と3ステップ判定フロー&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第4章: 巨大バイナリ混入の悲劇 〜.mdfをGitにpushするとリポジトリが崩壊する理由と.gitignoreの徹底〜&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第5章: C# / .NET 現場での実践：appsettings.json（設定）とSQL Server実データ（Volume）の共存設計&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第6章: チーム開発でのGit＆Docker運用ルール策定ガイドライン&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第7章: 第6部総決算のまとめと理解度チェッククイズ（次回予告：第7部 Dockerネットワーク入門）&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第1章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第1章: 共有フォルダ破綻の歴史に学ぶ 〜なぜ「何でも詰め込み」は失敗するのか？〜&lt;/h2&gt;
        &lt;p&gt;
            かつてのオンプレミスや仮想マシン（Hyper-V / VMware）全盛の時代、社内ネットワークには必ず &lt;code&gt;\\fileserver\dev_share&lt;/code&gt; のような「開発用共有フォルダ」が存在していました。&lt;br/&gt;
            そこには以下のようなあらゆる種類のファイルが無法地帯のように混在していました：
        &lt;/p&gt;
        &lt;ul style=&quot;line-height: 1.8; color: #334155;&quot;&gt;
            &lt;li&gt;Visual StudioのソリューションファイルやC#ソースコード&lt;/li&gt;
            &lt;li&gt;SQL Serverにアタッチされている生の &lt;code&gt;app_data.mdf&lt;/code&gt; や &lt;code&gt;app_log.ldf&lt;/code&gt;&lt;/li&gt;
            &lt;li&gt;各エンジニアが手元で実行した出力ログやエラーダンプ&lt;/li&gt;
            &lt;li&gt;本番サーバー接続文字列がハードコードされた設定ファイル&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;
            このような「何でも詰め込み」運用がもたらした結末は、多くのベテランエンジニアが身をもって体験してきた通り &lt;strong&gt;「完全な破綻」&lt;/strong&gt; でした。
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1kDokl130p6xJUICHlWs7YJZuSbJ1F0iw&quot; alt=&quot;共有フォルダの破綻 vs 現代の境界線&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】旧来の共有フォルダ破綻（何でも混在） vs 現代の3層分離（コード・構成・データ）&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;p&gt;
            上図（左側）をご覧ください。共有フォルダでファイルを共有すると、次のような致命的トラブルが連日発生しました：
        &lt;/p&gt;
        &lt;div style=&quot;background: #fff1f2; border-left: 6px solid #e11d48; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
            &lt;h4 style=&quot;margin: 0 0 8px 0; color: #be123c; font-size: 16px;&quot;&gt;⚠️ 共有フォルダ運用が引き起こした3大悲劇&lt;/h4&gt;
            &lt;ol style=&quot;margin: 0; padding-left: 20px; font-size: 14.5px; line-height: 1.8; color: #4c0519;&quot;&gt;
                &lt;li&gt;&lt;strong&gt;ファイルロックとデータベース破損:&lt;/strong&gt; 誰かがSQL Server Management Studio（SSMS）で接続したままにして排他ロックがかかり、他のメンバーが作業できなくなる。最悪の場合、同時書き込みでmdfヘッダーが破損し、全員のデータが全滅する。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;データの先祖返りとブラックボックス化:&lt;/strong&gt; 「最新のDBデータはどれ？」「backup_20261020_final2.bak って誰が作ったの？」と誰も全体像を把握できなくなる。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;秘密情報の漏洩リスク:&lt;/strong&gt; パスワードや機密データが誰でもアクセス可能な平文ファイルとして放置され、情報セキュリティ上の重大な脆弱性となる。&lt;/li&gt;
            &lt;/ol&gt;
        &lt;/div&gt;
        &lt;p&gt;
            現代のコンテナ開発では、この苦い歴史の反省から &lt;strong&gt;「ファイルをその性質（ライフサイクルと変更頻度）に応じて厳密に分類し、それぞれ最適な仕組みで管理する」&lt;/strong&gt; というパラダイムシフトが確立されています。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第2章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第2章: 現代コンテナ開発における「3層分離（コード・構成・データ）」の原則&lt;/h2&gt;
        &lt;p&gt;
            DockerとGitを組み合わせたモダンな開発環境では、すべての構成要素を以下の &lt;strong&gt;「3層」&lt;/strong&gt; に厳格に分離して設計します。
        &lt;/p&gt;

        &lt;div style=&quot;display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; margin: 24px 0;&quot;&gt;
            &lt;!-- 層1 --&gt;
            &lt;div style=&quot;background: #f0f9ff; border: 1px solid #bae6fd; border-radius: 8px; padding: 18px;&quot;&gt;
                &lt;div style=&quot;font-size: 20px; font-weight: bold; color: #0284c7; margin-bottom: 8px;&quot;&gt;① コード層（Git管理）&lt;/div&gt;
                &lt;div style=&quot;font-size: 13px; color: #0369a1; font-weight: bold; margin-bottom: 8px;&quot;&gt;対象: ソースコード・構成定義&lt;/div&gt;
                &lt;p style=&quot;margin: 0; font-size: 14px; color: #334155; line-height: 1.7;&quot;&gt;
                    C#の &lt;code&gt;.cs&lt;/code&gt; ファイル、&lt;code&gt;.csproj&lt;/code&gt;、&lt;code&gt;Dockerfile&lt;/code&gt;、&lt;code&gt;docker-compose.yml&lt;/code&gt;。&lt;br/&gt;
                    テキストベースで記述され、変更履歴（コミットログ）が厳密に記録されるべきチーム共通の資産。
                &lt;/p&gt;
            &lt;/div&gt;
            &lt;!-- 層2 --&gt;
            &lt;div style=&quot;background: #fff7ed; border: 1px solid #fed7aa; border-radius: 8px; padding: 18px;&quot;&gt;
                &lt;div style=&quot;font-size: 20px; font-weight: bold; color: #ea580c; margin-bottom: 8px;&quot;&gt;② 構成・機密層（.env / 除外）&lt;/div&gt;
                &lt;div style=&quot;font-size: 13px; color: #c2410c; font-weight: bold; margin-bottom: 8px;&quot;&gt;対象: 環境変数・パスワード・接続文字列&lt;/div&gt;
                &lt;p style=&quot;margin: 0; font-size: 14px; color: #334155; line-height: 1.7;&quot;&gt;
                    &lt;code&gt;.env&lt;/code&gt; や &lt;code&gt;docker-compose.override.yml&lt;/code&gt;。&lt;br/&gt;
                    環境ごとに異なる機密情報。Gitにはテンプレート（&lt;code&gt;.env.example&lt;/code&gt;）のみをコミットし、実ファイルは &lt;code&gt;.gitignore&lt;/code&gt; で完全除外。
                &lt;/p&gt;
            &lt;/div&gt;
            &lt;!-- 層3 --&gt;
            &lt;div style=&quot;background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 18px;&quot;&gt;
                &lt;div style=&quot;font-size: 20px; font-weight: bold; color: #16a34a; margin-bottom: 8px;&quot;&gt;③ データ・状態層（Volume管理）&lt;/div&gt;
                &lt;div style=&quot;font-size: 13px; color: #15803d; font-weight: bold; margin-bottom: 8px;&quot;&gt;対象: DB実データ・ログ・ユーザー生成物&lt;/div&gt;
                &lt;p style=&quot;margin: 0; font-size: 14px; color: #334155; line-height: 1.7;&quot;&gt;
                    SQL Serverの &lt;code&gt;.mdf/.ldf&lt;/code&gt;、ユーザー投稿画像、アクセスログ。&lt;br/&gt;
                    サイズが巨大で頻繁に更新されるバイナリ。Gitには一切入れず、Dockerの &lt;strong&gt;Named Volume&lt;/strong&gt; に逃がして永続化。
                &lt;/p&gt;
            &lt;/div&gt;
        &lt;/div&gt;

        &lt;p&gt;
            この3層分離を徹底することで、「コードは安全に共有され」「パスワードは漏洩せず」「データベースはコンテナ破棄時も確実に保護される」という強固なアーキテクチャが完成します。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第3章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第3章: 現場向け「ファイル行き先判定マトリクス」と3ステップ判定フロー&lt;/h2&gt;
        &lt;p&gt;
            プロジェクトに新しいファイルやフォルダが追加された際、チームメンバーが迷わず正しく配置できるよう、以下の &lt;strong&gt;「判定3ステップフロー」&lt;/strong&gt; を確立しましょう。
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1qni12TXaH03hkwvJVXMTPHd3wfRP2U3B&quot; alt=&quot;ファイルの行き先判定3ステップ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】現場で迷わない！ファイルの行き先判定3ステップマトリクス&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;p&gt;
            このフローに基づいた現場向け判定マトリクスがこちらです：
        &lt;/p&gt;

        &lt;!-- マトリクステーブル --&gt;
        &lt;div style=&quot;overflow-x: auto; margin: 24px 0;&quot;&gt;
            &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 14.5px; text-align: left;&quot;&gt;
                &lt;thead&gt;
                    &lt;tr style=&quot;background: #0f172a; color: #ffffff;&quot;&gt;
                        &lt;th style=&quot;padding: 12px 14px; border: 1px solid #334155;&quot;&gt;ファイル種類&lt;/th&gt;
                        &lt;th style=&quot;padding: 12px 14px; border: 1px solid #334155;&quot;&gt;具体例&lt;/th&gt;
                        &lt;th style=&quot;padding: 12px 14px; border: 1px solid #334155;&quot;&gt;管理場所&lt;/th&gt;
                        &lt;th style=&quot;padding: 12px 14px; border: 1px solid #334155;&quot;&gt;理由・注意点&lt;/th&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                    &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;C# ソースコード&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;*.cs&lt;/code&gt;, &lt;code&gt;*.csproj&lt;/code&gt;, &lt;code&gt;*.sln&lt;/code&gt;&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #0284c7; font-weight: bold;&quot;&gt;Git管理&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;アプリの本体。チームで共同開発。&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;インフラ定義ファイル&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;Dockerfile&lt;/code&gt;, &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #0284c7; font-weight: bold;&quot;&gt;Git管理&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;環境の再現手順（IaC）。全員が同じ定義で起動。&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;アプリケーション共通設定&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;appsettings.json&lt;/code&gt;&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #0284c7; font-weight: bold;&quot;&gt;Git管理&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;ログ設定や基本オプション。機密パスワードは含めない。&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;環境固有の機密情報&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;*.secrets.json&lt;/code&gt;&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #ea580c; font-weight: bold;&quot;&gt;Git除外（.gitignore）&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;DBパスワードやAPI鍵。漏洩防止のためGit厳禁。&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;設定ファイルのひな形&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;.env.example&lt;/code&gt;&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #0284c7; font-weight: bold;&quot;&gt;Git管理&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;新人参加者がコピーして自分の &lt;code&gt;.env&lt;/code&gt; を作るための見本。&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;データベース実データ&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;*.mdf&lt;/code&gt;, &lt;code&gt;*.ldf&lt;/code&gt;, &lt;code&gt;*.bak&lt;/code&gt;&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;Docker Named Volume&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;巨大バイナリ。Gitに絶対入れずDocker管理領域へ。&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;ビルド成果物・一時ファイル&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;bin/&lt;/code&gt;, &lt;code&gt;obj/&lt;/code&gt;, &lt;code&gt;.vs/&lt;/code&gt;&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #ea580c; font-weight: bold;&quot;&gt;Git除外（.gitignore）&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;ソースからいつでも再生成可能。リポジトリ汚染の主因。&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;初期マスタデータSQL&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;init.sql&lt;/code&gt;, &lt;code&gt;migrations/*.cs&lt;/code&gt;&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #0284c7; font-weight: bold;&quot;&gt;Git管理&lt;/td&gt;
                        &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;テーブル定義や初期投入用。テキスト形式なのでGitで共有。&lt;/td&gt;
                    &lt;/tr&gt;
                &lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 第4章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第4章: 巨大バイナリ混入の悲劇 〜.mdfをGitにpushするとリポジトリが崩壊する理由と.gitignoreの徹底〜&lt;/h2&gt;
        &lt;p&gt;
            なぜデータベースの実データファイル（&lt;code&gt;.mdf&lt;/code&gt; や &lt;code&gt;.ldf&lt;/code&gt;）をGitにコミットしてはいけないのでしょうか？&lt;br/&gt;
            その理由は、&lt;strong&gt;「Gitの内部データ構造（スナップショット方式）」&lt;/strong&gt; にあります。
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/10uV1elF6iNuBwt2nqrxwBMAvXm_771Nq&quot; alt=&quot;巨大バイナリ混入の悲劇と防止&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】巨大バイナリ（mdf/ldf）混入の悲劇と .gitignore 徹底による完全防御&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;p&gt;
            Gitはテキストファイル（C#コードなど）であれば行単位のコンパクトな差分（delta）を保存しますが、バイナリファイルに対しては &lt;strong&gt;「1バイト変わるだけでもファイル全体を丸ごと新しいスナップショットとしてコミット履歴（&lt;code&gt;.git/objects&lt;/code&gt;）に保存」&lt;/strong&gt; します。
        &lt;/p&gt;

        &lt;div style=&quot;background: #fff1f2; border-left: 6px solid #e11d48; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
            &lt;h4 style=&quot;margin: 0 0 8px 0; color: #be123c; font-size: 16px;&quot;&gt;💥 巨大バイナリ事故のシミュレーション&lt;/h4&gt;
            &lt;p style=&quot;margin: 0; font-size: 14.5px; line-height: 1.8; color: #4c0519;&quot;&gt;
                例えば 2GB の &lt;code&gt;testdata.mdf&lt;/code&gt; をGitにコミットしたとします。&lt;br/&gt;
                その後、SQL Serverでレコードを1件INSERTして再度コミットすると、さらに 2GB の新しいバイナリが &lt;code&gt;.git&lt;/code&gt; に追加されます。&lt;br/&gt;
                これを10回繰り返すだけで、リポジトリの容量は &lt;strong&gt;20GB&lt;/strong&gt; を超えます！&lt;br/&gt;
                新しくチームに参加したエンジニアが &lt;code&gt;git clone&lt;/code&gt; を実行すると、ダウンロードに数時間かかり、通信タイムアウトで失敗し続けるという悪夢が現実になります。
            &lt;/p&gt;
        &lt;/div&gt;

        &lt;p&gt;
            さらに恐ろしいことに、後から &lt;code&gt;git rm testdata.mdf&lt;/code&gt; を実行してファイルを消去しても、&lt;strong&gt;過去のコミット履歴の中には20GBのバイナリが残り続けます&lt;/strong&gt;。&lt;br/&gt;
            履歴から完全に消去するには &lt;code&gt;git-filter-repo&lt;/code&gt; などの危険な履歴書き換えコマンドが必要になり、チーム全員のローカル環境のリセットを強いられます。&lt;br/&gt;
            この悲劇を100%未然に防ぐ唯一の方法が、&lt;strong&gt;プロジェクト開始初日における &lt;code&gt;.gitignore&lt;/code&gt; の徹底&lt;/strong&gt; です！
        &lt;/p&gt;

        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 20px 0; overflow-x: auto;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #64748b;&quot;&gt;# Docker × C# / .NET プロジェクト必須の .gitignore テンプレート&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;### 1. データベース実データ・バックアップ（絶対にコミット禁止！） ###&lt;/span&gt;
*.mdf
*.ldf
*.ndf
*.bak
*.trn
*.db
*.sqlite

&lt;span style=&quot;color: #64748b;&quot;&gt;### 2. 環境変数・秘匿設定ファイル ###&lt;/span&gt;
.env
.env.local
.env.*.local
*.secrets.json

&lt;span style=&quot;color: #64748b;&quot;&gt;### 3. C# / .NET ビルド成果物・キャッシュ ###&lt;/span&gt;
[Bb]in/
[Oo]bj/
[Dd]ebug/
[Rr]elease/
*.user
*.suo
.vs/
.idea/

&lt;span style=&quot;color: #64748b;&quot;&gt;### 4. ログファイル・一時出力 ###&lt;/span&gt;
*.log
logs/
temp/
docker_volumes/
&lt;/pre&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 第5章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第5章: C# / .NET 現場での実践：appsettings.json（設定）とSQL Server実データ（Volume）の共存設計&lt;/h2&gt;
        &lt;p&gt;
            C# / ASP.NET Core のエンタープライズ現場では、この境界線をどのようにコードとインフラで表現するのでしょうか？&lt;br/&gt;
            具体的な &lt;code&gt;appsettings.json&lt;/code&gt; と &lt;code&gt;docker-compose.yml&lt;/code&gt; の連携設計を見てみましょう。
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1JR3bhQryyn9NImtsVOigs1U_L7-EGNl2&quot; alt=&quot;C#現場の設定と実データの分離&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】C#エンタープライズ現場における設定（Git）と実データ（Volume）の分離共存設計&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;p&gt;
            上図をご覧ください。設計の勘所は以下の2点です：
        &lt;/p&gt;
        &lt;ol style=&quot;line-height: 1.8; color: #334155;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;設定の抽象化（Git共有）:&lt;/strong&gt; &lt;code&gt;appsettings.json&lt;/code&gt; には「DBのホスト名（サービス名: &lt;code&gt;db&lt;/code&gt;）」や「ポート（&lt;code&gt;1433&lt;/code&gt;）」といった構造のみを記述し、パスワード部分は環境変数で上書き可能なプレースホルダーにしておきます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;データの完全委任（Volume管理）:&lt;/strong&gt; SQL Serverコンテナが生成・管理する &lt;code&gt;/var/opt/mssql/data&lt;/code&gt; は、DockerのNamed Volume（&lt;code&gt;sqlserver_data&lt;/code&gt;）にマウントします。&lt;/li&gt;
        &lt;/ol&gt;

        &lt;!-- コード例: appsettings.json --&gt;
        &lt;h3 style=&quot;font-size: 16.5px; color: #0f172a; margin-top: 24px;&quot;&gt;① C#側の設定ファイル（Gitで管理・共有）&lt;/h3&gt;
        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 16px 0; overflow-x: auto;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #64748b;&quot;&gt;// appsettings.json （パスワードは空文字または環境変数上書き前提）&lt;/span&gt;
{
  &lt;span style=&quot;color: #7dd3fc;&quot;&gt;&quot;Logging&quot;&lt;/span&gt;: {
    &lt;span style=&quot;color: #7dd3fc;&quot;&gt;&quot;LogLevel&quot;&lt;/span&gt;: {
      &lt;span style=&quot;color: #7dd3fc;&quot;&gt;&quot;Default&quot;&lt;/span&gt;: &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;Information&quot;&lt;/span&gt;,
      &lt;span style=&quot;color: #7dd3fc;&quot;&gt;&quot;Microsoft.AspNetCore&quot;&lt;/span&gt;: &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;Warning&quot;&lt;/span&gt;
    }
  },
  &lt;span style=&quot;color: #7dd3fc;&quot;&gt;&quot;ConnectionStrings&quot;&lt;/span&gt;: {
    &lt;span style=&quot;color: #64748b;&quot;&gt;// ホスト名はコンテナサービス名「db」を指定！パスワードはComposeの環境変数で注入される&lt;/span&gt;
    &lt;span style=&quot;color: #7dd3fc;&quot;&gt;&quot;DefaultConnection&quot;&lt;/span&gt;: &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;Server=db,1433;Database=OrderDb;User Id=sa;Password=${DB_PASSWORD};TrustServerCertificate=True;&quot;&lt;/span&gt;
  }
}
&lt;/pre&gt;
        &lt;/div&gt;

        &lt;!-- コード例: docker-compose.yml --&gt;
        &lt;h3 style=&quot;font-size: 16.5px; color: #0f172a; margin-top: 24px;&quot;&gt;② docker-compose.yml（Gitで管理・Volumeとパスワードを結合）&lt;/h3&gt;
        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 16px 0; overflow-x: auto;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #7dd3fc;&quot;&gt;services:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;webapi:&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;build:&lt;/span&gt; .
    &lt;span style=&quot;color: #f472b6;&quot;&gt;ports:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;5000:5000&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;environment:&lt;/span&gt;
      &lt;span style=&quot;color: #64748b;&quot;&gt;# .env からパスワードを読み込み、C#の接続文字列を環境変数で完全注入&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;ConnectionStrings__DefaultConnection=Server=db,1433;Database=OrderDb;User Id=sa;Password=${SA_PASSWORD};TrustServerCertificate=True;&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;depends_on:&lt;/span&gt;
      &lt;span style=&quot;color: #cbd5e1;&quot;&gt;db:&lt;/span&gt;
        &lt;span style=&quot;color: #cbd5e1;&quot;&gt;condition:&lt;/span&gt; service_healthy

  &lt;span style=&quot;color: #38bdf8;&quot;&gt;db:&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;image:&lt;/span&gt; mcr.microsoft.com/mssql/server:2022-latest
    &lt;span style=&quot;color: #f472b6;&quot;&gt;environment:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;ACCEPT_EULA=Y&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;MSSQL_SA_PASSWORD=${SA_PASSWORD}&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;volumes:&lt;/span&gt;
      &lt;span style=&quot;color: #64748b;&quot;&gt;# ★実データ（.mdf / .ldf）はNamed Volumeに完全に退避！&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;sqlserver_data:/var/opt/mssql/data&lt;/span&gt;

&lt;span style=&quot;color: #64748b;&quot;&gt;# 名前付きボリュームの宣言（Dockerホスト領域で独立永続化）&lt;/span&gt;
&lt;span style=&quot;color: #7dd3fc;&quot;&gt;volumes:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;sqlserver_data:&lt;/span&gt;
&lt;/pre&gt;
        &lt;/div&gt;

        &lt;p&gt;
            この構成にすることで、チームの誰もが生のDBファイルをGitにコミットすることなく、&lt;code&gt;docker compose up -d&lt;/code&gt; を実行するだけで即座に安全で完全なローカル開発環境を立ち上げることができます。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第6章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第6章: チーム開発でのGit＆Docker運用ルール策定ガイドライン&lt;/h2&gt;
        &lt;p&gt;
            「Git管理とVolumeの境界線」をチーム全員で遵守するために、プロジェクトの &lt;code&gt;README.md&lt;/code&gt; や開発ガイドラインに以下の &lt;strong&gt;4大ゴールデンルール&lt;/strong&gt; を明記しておくことを強く推奨します。
        &lt;/p&gt;

        &lt;div style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 22px 24px; margin: 24px 0;&quot;&gt;
            &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 16px; font-size: 18px;&quot;&gt;📋 チーム開発のための4大ゴールデンルール&lt;/h3&gt;
            
            &lt;div style=&quot;margin-bottom: 16px;&quot;&gt;
                &lt;strong style=&quot;color: #0284c7; font-size: 15.5px;&quot;&gt;ルール1：初期データは「mdf」ではなく「Migration」または「init.sql」で共有せよ&lt;/strong&gt;
                &lt;p style=&quot;margin: 4px 0 0 0; font-size: 14.5px; color: #475569;&quot;&gt;
                    開発用の初期データやテーブル構造を渡したい時は、バイナリのmdfファイルを渡すのではなく、EF Coreの &lt;code&gt;dotnet ef migrations&lt;/code&gt; や、テキスト形式の &lt;code&gt;seed_data.sql&lt;/code&gt; をGitで共有します。
                &lt;/p&gt;
            &lt;/div&gt;

            &lt;div style=&quot;margin-bottom: 16px;&quot;&gt;
                &lt;strong style=&quot;color: #ea580c; font-size: 15.5px;&quot;&gt;ルール2：リポジトリ直下の .env はコミット厳禁！ .env.example をメンテナンスせよ&lt;/strong&gt;
                &lt;p style=&quot;margin: 4px 0 0 0; font-size: 14.5px; color: #475569;&quot;&gt;
                    環境変数キーを追加した時は、必ず &lt;code&gt;.env.example&lt;/code&gt; にダミー値（例: &lt;code&gt;SA_PASSWORD=YourPasswordHere123!&lt;/code&gt;）を追記してコミットします。新メンバーはこれをコピーして手元で動かせます。
                &lt;/p&gt;
            &lt;/div&gt;

            &lt;div style=&quot;margin-bottom: 16px;&quot;&gt;
                &lt;strong style=&quot;color: #16a34a; font-size: 15.5px;&quot;&gt;ルール3：データベースをリセットしたい時は Volume を再作成せよ&lt;/strong&gt;
                &lt;p style=&quot;margin: 4px 0 0 0; font-size: 14.5px; color: #475569;&quot;&gt;
                    手元のテストデータを完全にクリーンアップして初期状態に戻したい時は、&lt;code&gt;docker compose down -v&lt;/code&gt; を実行するだけで、Named Volumeが初期化されマイグレーションが再実行されます。
                &lt;/p&gt;
            &lt;/div&gt;

            &lt;div&gt;
                &lt;strong style=&quot;color: #9333ea; font-size: 15.5px;&quot;&gt;ルール4：プルリクエスト時の差分チェックで「.mdf / bin」の混入を即時却下せよ&lt;/strong&gt;
                &lt;p style=&quot;margin: 4px 0 0 0; font-size: 14.5px; color: #475569;&quot;&gt;
                    GitHub ActionsなどのCIパイプラインで、万が一バイナリファイルや不要フォルダが含まれていた場合は自動でビルドを失敗させる静的解析ガードを設置するとさらに完璧です。
                &lt;/p&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 第7章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第7章: 第6部総決算のまとめと理解度チェッククイズ&lt;/h2&gt;
        &lt;p&gt;
            これで第6部「データの永続化とボリューム（Volume &amp; Bind Mount）」のカリキュラムはすべて完了です！&lt;br/&gt;
            コンテナのステートレスな原則（Day 27）、Named Volumeによる安全なデータ保持（Day 28）、Bind Mountによる爆速ホットリロード（Day 29）、そして今回のGitとVolumeの境界線（Day 30）を学んだことで、&lt;strong&gt;データ永続化と開発効率を完璧に両立させるプロフェッショナルな基盤&lt;/strong&gt; が完成しました！
        &lt;/p&gt;

        &lt;!-- 理解度チェッククイズ --&gt;
        &lt;div style=&quot;background: linear-gradient(135deg, #f0fdf4 0%, #e0f2fe 100%); border: 1px solid #86efac; border-radius: 8px; padding: 22px 24px; margin: 30px 0;&quot;&gt;
            &lt;h3 style=&quot;color: #166534; margin-top: 0; margin-bottom: 14px; font-size: 18px; display: flex; align-items: center;&quot;&gt;
                &lt;span style=&quot;font-size: 22px; margin-right: 8px;&quot;&gt;🎯&lt;/span&gt;
                理解度チェッククイズ！
            &lt;/h3&gt;
            &lt;p style=&quot;font-size: 15px; color: #1e293b; margin-bottom: 14px;&quot;&gt;
                &lt;strong&gt;問:&lt;/strong&gt; 新しい開発メンバーが「自分の手元のSQL Serverデータをチーム全員に配りたいので、mdfファイルをGitにコミットしてpushしました！」と言ってきました。シニアエンジニアとしてどうアドバイスし、どのように解決すべきでしょうか？
            &lt;/p&gt;
            &lt;details style=&quot;background: #ffffff; padding: 14px 18px; border-radius: 6px; border: 1px solid #bbf7d0; cursor: pointer;&quot;&gt;
                &lt;summary style=&quot;font-weight: bold; color: #0284c7;&quot;&gt;正解と解説を確認する&lt;/summary&gt;
                &lt;div style=&quot;margin-top: 12px; font-size: 14.5px; line-height: 1.8; color: #334155;&quot;&gt;
                    &lt;p style=&quot;margin: 0 0 8px 0; color: #e11d48; font-weight: bold;&quot;&gt;【アドバイスと対応手順】&lt;/p&gt;
                    &lt;ol style=&quot;margin: 0; padding-left: 20px;&quot;&gt;
                        &lt;li&gt;&lt;strong&gt;即時差し戻しと履歴の除去:&lt;/strong&gt; mdfファイルは巨大バイナリであり、リポジトリ肥大化・clone遅延の主因となるため、直ちにpushを差し戻すか &lt;code&gt;git reset&lt;/code&gt; でコミットを取り消す。&lt;/li&gt;
                        &lt;li&gt;&lt;strong&gt;.gitignore の適用:&lt;/strong&gt; &lt;code&gt;*.mdf&lt;/code&gt;, &lt;code&gt;*.ldf&lt;/code&gt; を &lt;code&gt;.gitignore&lt;/code&gt; に追加して再コミットを防止する。&lt;/li&gt;
                        &lt;li&gt;&lt;strong&gt;シードデータ（SQL/Migration）での共有:&lt;/strong&gt; データをチームに配る場合は、mdfファイルではなく EF Core の &lt;code&gt;HasData()&lt;/code&gt; によるシーディングスクリプト、または &lt;code&gt;init.sql&lt;/code&gt; のようなテキストスクリプトを作成してGit管理する。&lt;/li&gt;
                        &lt;li&gt;&lt;strong&gt;Volumeの利用:&lt;/strong&gt; 各メンバーは &lt;code&gt;docker compose up&lt;/code&gt; 時にそのスクリプトを各自の Named Volume に流し込む運用に切り替える。&lt;/li&gt;
                    &lt;/ol&gt;
                &lt;/div&gt;
            &lt;/details&gt;
        &lt;/div&gt;

        &lt;!-- 次回予告 --&gt;
        &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 20px 24px; margin: 30px 0; border: 1px solid #cbd5e1;&quot;&gt;
            &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 10px; font-size: 17px;&quot;&gt;🚀 次回予告：第7部「Dockerネットワークの基礎とサービス間通信」突入！&lt;/h3&gt;
            &lt;p style=&quot;margin: 0; font-size: 15px; line-height: 1.8; color: #334155;&quot;&gt;
                次回Day 31からは、いよいよ &lt;strong&gt;第7部「Dockerネットワーク」&lt;/strong&gt; がスタートします！&lt;br/&gt;
                「なぜ &lt;code&gt;docker-compose.yml&lt;/code&gt; の中では &lt;code&gt;localhost&lt;/code&gt; ではなくサービス名（&lt;code&gt;db&lt;/code&gt;）で通信できるのか？」&lt;br/&gt;
                Docker内部に自動生成される仮想ブリッジネットワーク（Bridge Network）やDNSサーバーの驚くべき仕組みを徹底的に解き明かします。お楽しみに！
            &lt;/p&gt;
        &lt;/div&gt;

    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/6896788009221641826/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-30gitvolume-gitgitenvvolume3mdfgiti.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/6896788009221641826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/6896788009221641826'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-30gitvolume-gitgitenvvolume3mdfgiti.html' title='【Day 30】Git管理すべきファイルとVolumeに逃がすべきデータの境界線 〜コード（Git）・構成（Git/.env）・データ（Volume）の3層分離、巨大mdfバイナリ混入事故の防止、.gitignore徹底、チーム開発共有ルール〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1RUIF2YNYTmmwgKWrms3Wa6GeEU_olj9Z=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-8265595291148635780</id><published>2026-10-25T18:10:36.718+09:00</published><updated>2026-10-25T18:10:36.718+09:00</updated><title type='text'>【Day 27】git worktree で再ビルドなしの超高速ブランチ並行開発</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1dol4Vw1RU1wEWHyj77nd1REFPn88ZBWe&quot; alt=&quot;Day 27 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 27】git worktree で再ビルドなしの超高速ブランチ並行開発&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 26では、第5部の集大成として「AIエージェントを活用したケーススタディ自動実行（Issue-to-PR）」を学び、現代の自律型コーディング環境とGitの強力な連携をマスターしました。&lt;br/&gt;
            そして本日のDay 27より、いよいよ&lt;strong&gt;【第6部: プロの調査・保守・作業効率化テクニック】&lt;/strong&gt;がスタートします！&lt;br/&gt;
            第1弾のテーマは、チーム開発や現場で活躍する全エンジニアに知ってほしいGitの神機能——&lt;strong&gt;【git worktree で再ビルドなしの超高速ブランチ並行開発】&lt;/strong&gt;です！&lt;br/&gt;
            「新機能の開発に没頭している最中、突然本番環境で緊急障害が発生して調査を頼まれた……。ブランチを切り替えたら、Visual Studioが巨大なC#ソリューション全体をゼロから再ビルドし始め、NuGetパッケージの再復元で10分以上待たされた」&lt;br/&gt;
            「調査が終わって元のブランチに戻ってきたら、またしても全件再ビルドで待ち時間……。開いていたタブやブレークポイントも消えて集中力が完全に削がれた」&lt;br/&gt;
            こうした苦い経験は、エンジニアなら誰しも一度はあるはずです。&lt;br/&gt;
            かつてのSubversion (SVN) では別フォルダにチェックアウトして複数開くことができましたが、Gitでも完全に別のフォルダへ別ブランチを即時展開し、Visual Studioを2つ同時に開いて並行デバッグできる仕組みが存在します。それが &lt;strong&gt;&lt;code&gt;git worktree&lt;/code&gt;&lt;/strong&gt; です！&lt;br/&gt;
            リポジトリを丸ごと別cloneする必要はありません。コミット履歴やローカルブランチは完全に共有されたまま、ワーキングディレクトリとビルド生成物（bin/obj）だけを物理的に分離できます。&lt;br/&gt;
            本日は、この &lt;code&gt;git worktree&lt;/code&gt; の仕組みから、実務でのC#並行開発テクニック、ポート番号の競合回避、そして安全な後片付け手順まで、余すところなく徹底解説します！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        Gitの最大の魅力は「軽量なブランチ作成と瞬時の切り替え」ですが、&lt;strong&gt;「コンパイル言語（C# / .NET）の巨大ソリューション」&lt;/strong&gt;においては、ブランチ切り替え時にファイルタイムスタンプが更新され、Visual Studioが全プロジェクトの再ビルドやNuGet復元を実行してしまうという現実の壁が存在します。&lt;br/&gt;
        この「ビルド待ち時間」と「コンテキストスイッチの消耗」を完全に解消する切り札が &lt;code&gt;git worktree&lt;/code&gt; です。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;従来の &lt;code&gt;git switch&lt;/code&gt; によるファイル一括置換と、巨大C#ソリューション再ビルド待ちの課題を理解する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git worktree&lt;/code&gt; の内部アーキテクチャ（単一の.gitディレクトリ共有 × 複数作業フォルダ展開）を把握する&lt;/li&gt;
            &lt;li&gt;リポジトリを丸ごと &lt;code&gt;git clone&lt;/code&gt; し直す手法と比較した圧倒的メリット（容量節約・履歴即時共有・高速展開）を学ぶ&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git worktree add&lt;/code&gt;、&lt;code&gt;list&lt;/code&gt;、&lt;code&gt;remove&lt;/code&gt;、&lt;code&gt;prune&lt;/code&gt; の必須ライフサイクルコマンドを習得する&lt;/li&gt;
            &lt;li&gt;Visual Studioを2画面で同時起動し、本番Hotfix調査と機能開発を並行デバッグする実戦手順（ポート競合回避を含む）を身につける&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: ブランチ切り替えの苦悩 vs git worktree --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】従来のブランチ切り替えの苦悩 vs git worktree の即時性&lt;/h2&gt;
    &lt;p&gt;
        まずは、従来のブランチ切り替え（&lt;code&gt;git switch&lt;/code&gt; / &lt;code&gt;checkout&lt;/code&gt;）と &lt;code&gt;git worktree&lt;/code&gt; の挙動の違いを比較してみましょう。
    &lt;/p&gt;

    &lt;!-- 図解① --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1k1Ae5_yFTYLk9EpnDN_ugCcIfIoVyqQ1&quot; alt=&quot;ブランチ切り替えの苦悩 vs git worktree の即時性&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】従来のgit switch（再ビルド・NuGet復元待ち地獄） vs git worktree（フォルダ別展開で即時起動）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        Gitの基本動作では、1つの作業ディレクトリ（Working Directory）内でファイルを丸ごと差し替えることでブランチを切り替えます。&lt;br/&gt;
        スクリプト言語などでは一瞬ですが、C#やC++などのコンパイル言語では以下の深刻な問題が発生します。
    &lt;/p&gt;

    &lt;div style=&quot;background: #fff1f2; border-left: 5px solid #e11d48; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #be123c; font-size: 16.5px;&quot;&gt;💥 巨大C#ソリューションでの「ブランチ切り替え地獄」&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85; color: #4c0519;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;ファイルのタイムスタンプ更新による全件リビルド:&lt;/strong&gt; ソースコードが数万行〜数百プロジェクトに及ぶ場合、&lt;code&gt;bin&lt;/code&gt; や &lt;code&gt;obj&lt;/code&gt; 内の中間生成物が無効化され、ビルド完了まで5〜10分以上の待機時間が発生する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;NuGetパッケージの再復元（Restore）:&lt;/strong&gt; ブランチ間でパッケージバージョンが異なると、Visual StudioがバックグラウンドでNuGetパッケージの復元を開始し、CPUファンが激しく回転してPCが重くなる。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;IDE状態（タブ・ブレークポイント）の喪失:&lt;/strong&gt; 開いていたエディタのタブ、設定したブレークポイント、デバッグの実行状態がリセットされ、元の作業に戻った際に「どこまで書いたか」を思い出すのに大きな精神的エネルギーを消費する。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        かつてSubversion (SVN) を使っていたエンジニアからは、「SVNなら別フォルダにチェックアウト（Checkout）して複数同時に開けたのに、Gitは1つのフォルダしか使えないから不便だ」という声をよく聞きます。&lt;br/&gt;
        しかし、それは誤解です！ &lt;strong&gt;Gitには、SVNの複数チェックアウトの利点を完全に再現し、さらに超進化させた『git worktree』が備わっている&lt;/strong&gt;のです！
    &lt;/p&gt;

    &lt;!-- セクション③: 内部アーキテクチャ --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】git worktree の内部アーキテクチャ：なぜ別cloneより圧倒的に優れているのか？&lt;/h2&gt;
    &lt;p&gt;
        「別フォルダで作業したいなら、別の場所に &lt;code&gt;git clone&lt;/code&gt; すれば良いのでは？」と思うかもしれません。&lt;br/&gt;
        しかし、別cloneには重大な欠点があります。
    &lt;/p&gt;

    &lt;!-- 図解② --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1qX2VFfuTnziuR85EvNGi0pgKJoOKlci6&quot; alt=&quot;git worktree の内部アーキテクチャ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】1つの.git共有リポジトリ本体 × 複数の独立ワーキングディレクトリ展開構造&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #3b82f6; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #1d4ed8; font-size: 16.5px;&quot;&gt;📊 「git clone 複数作成」vs「git worktree」の決定的違い&lt;/strong&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 15px; color: #1e293b;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #dbeafe; border-bottom: 2px solid #93c5fd;&quot;&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left;&quot;&gt;比較項目&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left;&quot;&gt;別ディレクトリへ git clone&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px; text-align: left; color: #1e40af; font-weight: bold;&quot;&gt;git worktree（推奨）&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;ディスク消費量&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #dc2626;&quot;&gt;リポジトリ履歴（.git）を二重保存（数GB浪費）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #16a34a; font-weight: bold;&quot;&gt;.git は1つだけ共有！作業ファイル分のみ（極小）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;展開スピード&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #dc2626;&quot;&gt;ネットワーク通信や全履歴コピーで数分〜数十分&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #16a34a; font-weight: bold;&quot;&gt;ローカル内で瞬時にフォルダ生成（1秒以内）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;ローカルブランチ共有&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #dc2626;&quot;&gt;完全に別リポジトリ。push/fetchしないと見えない&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #16a34a; font-weight: bold;&quot;&gt;完全に同一リポジトリ！即座に全ブランチが同期&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px; font-weight: bold;&quot;&gt;Stash（退避）の共有&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #dc2626;&quot;&gt;共有不可（個別のstash領域）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px; color: #16a34a; font-weight: bold;&quot;&gt;同一リポジトリなので stash も相互に参照可能&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 25px; font-size: 19px;&quot;&gt;裏側の仕組み：ポインタとしての .git ファイル&lt;/h3&gt;
    &lt;p&gt;
        メインリポジトリ（最初にcloneしたフォルダ）には、これまで通り &lt;code&gt;.git&lt;/code&gt; という「ディレクトリ」が存在し、すべてのコミット履歴やオブジェクトが保存されています。&lt;br/&gt;
        一方、&lt;code&gt;git worktree add&lt;/code&gt; で新設された別フォルダの中を見ると、&lt;code&gt;.git&lt;/code&gt; はディレクトリではなく&lt;strong&gt;たった1行のテキストファイル&lt;/strong&gt;になっています！
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 追加ワークツリー内の .git ファイルの中身&lt;/span&gt;&lt;br/&gt;
        gitdir: C:/Project/MainRepo/.git/worktrees/hotfix-login
    &lt;/div&gt;
    &lt;p&gt;
        このポインタファイルのおかげで、Gitは追加ワークツリーでのコミットやブランチ操作をメインリポジトリの &lt;code&gt;.git&lt;/code&gt; へ直接記録します。&lt;br/&gt;
        つまり、&lt;strong&gt;「実体としての作業ファイル群（bin/objを含む）は完全に別フォルダに分かれつつ、Gitの頭脳（履歴・ブランチ）は完全に1つに繋がっている」&lt;/strong&gt;という理想的な構造が実現しているのです！
    &lt;/p&gt;

    &lt;!-- セクション④: 必須コマンドライフサイクル --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【図解・コマンド実践編】git worktree 必須コマンドのライフサイクル完全マスター&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;git worktree&lt;/code&gt; を使いこなすために覚えるべきコマンドは、たったの4つです！
    &lt;/p&gt;

    &lt;!-- 図解④ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1K6z-oJrqP2Q1RDARk7wSH2zzFuasvDyJ&quot; alt=&quot;git worktree 必須コマンドのライフサイクル&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】worktreeの追加（add）・確認（list）・安全削除（remove）・整合性修復（prune）の完全手順&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;1. ワークツリーを追加する（add）&lt;/h3&gt;
    &lt;p&gt;
        別フォルダにブランチを展開します。既存のブランチを指定することも、新ブランチを作成して展開することも可能です。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 16px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0; line-height: 1.6;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# パターンA: 既存のブランチ（例: hotfix-login）を別フォルダに展開&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; worktree add ../worktrees/hotfix-login hotfix-login&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# パターンB: mainから新ブランチ（-b）を作成しつつ同時に別フォルダに展開（実務で最も多用！）&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; worktree add -b hotfix/issue-501 ../worktrees/hotfix-issue-501 main
    &lt;/div&gt;
    &lt;div style=&quot;background: #fffbeb; border-left: 5px solid #f59e0b; padding: 14px 18px; margin: 15px 0; border-radius: 4px; font-size: 15px;&quot;&gt;
        &lt;strong style=&quot;color: #b45309;&quot;&gt;⚠️ Gitの安全保護ルール:&lt;/strong&gt;&lt;br/&gt;
        「同一リポジトリ内で、同じブランチを複数のワークツリーで同時にチェックアウトすることはできない」という安全規則があります。&lt;br/&gt;
        すでにメインで開いているブランチをworktreeで開こうとするとエラー（fatal: is already checked out）になるため、必ず別ブランチを指定または新規作成してください。
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;2. 現在のワークツリー一覧を確認する（list）&lt;/h3&gt;
    &lt;p&gt;
        どのフォルダにどのブランチが展開されているかを一覧表示します。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 16px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0; line-height: 1.6;&quot;&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; worktree list&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;C:/Project/MainRepo            5a3f2b1 [feature/shopping-cart]&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;C:/Project/worktrees/hotfix-issue-501  e91c784 [hotfix/issue-501]&lt;/span&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;3. 作業終了後にワークツリーを安全に削除する（remove）&lt;/h3&gt;
    &lt;p&gt;
        緊急対応や修正が終わり、コミット＆プッシュ（またはPR作成）が完了したら、ワークツリーを削除します。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 16px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0; line-height: 1.6;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# ワークツリーの削除（フォルダと内部メタデータが綺麗に削除されます）&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; worktree remove ../worktrees/hotfix-issue-501
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;4. 手動でフォルダを消してしまった場合のクリーンアップ（prune）&lt;/h3&gt;
    &lt;p&gt;
        もしエクスプローラーから直接フォルダをゴミ箱に捨ててしまった場合、Git内部に参照情報だけが残ってしまいます。その場合は &lt;code&gt;prune&lt;/code&gt; を実行すれば一瞬で整合性が修復されます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 16px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0; line-height: 1.6;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 孤立したワークツリー管理情報を一括整理&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; worktree prune
    &lt;/div&gt;

    &lt;!-- セクション⑤: C#現場での実戦ノウハウ --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【実戦C#編】Visual Studio 2画面同時デバッグとポート競合回避テクニック&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;git worktree&lt;/code&gt; をC#開発で真に活かすための、現場ならではの実戦テクニックを解説します。
    &lt;/p&gt;

    &lt;!-- 図解③ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1r4V9Sd0qz6NdF7SxEYjAeQHkxEeLDw4-&quot; alt=&quot;C#現場での2画面並行開発とポート競合回避&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】Visual Studio 2画面同時デバッグ（本番調査 vs 機能開発）とlaunchSettings.jsonによるポート分離&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; margin-top: 25px; font-size: 19px;&quot;&gt;テクニック1: Visual Studio を2つ起動して左右デュアルディスプレイに配置&lt;/h3&gt;
    &lt;p&gt;
        メインディレクトリのソリューションファイル（&lt;code&gt;MainRepo/MyApp.sln&lt;/code&gt;）と、追加ワークツリーのソリューションファイル（&lt;code&gt;hotfix-issue-501/MyApp.sln&lt;/code&gt;）をそれぞれVisual Studioで開きます。&lt;br/&gt;
        フォルダが完全に分かれているため、&lt;strong&gt;ソリューションのビルド生成物（bin/obj）が一切衝突しません！&lt;/strong&gt;&lt;br/&gt;
        左画面で「本番の障害再現・修正」を行いながら、右画面で「新機能の実装コード」を開いたまま参照できます。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 25px; font-size: 19px;&quot;&gt;テクニック2: launchSettings.json によるポート競合回避&lt;/h3&gt;
    &lt;p&gt;
        ASP.NET Core Web APIやBlazorアプリを2つ同時に「F5（デバッグ実行）」すると、同じポート番号（例: &lt;code&gt;https://localhost:7001&lt;/code&gt;）をバインドしようとして以下のエラーが発生します。
    &lt;/p&gt;
    &lt;div style=&quot;background: #fff1f2; border-left: 5px solid #e11d48; padding: 14px 18px; margin: 15px 0; border-radius: 4px; font-size: 14.5px; font-family: Consolas, monospace; color: #9f1239;&quot;&gt;
        System.IO.IOException: Failed to bind to address https://localhost:7001: address already in use.
    &lt;/div&gt;
    &lt;p&gt;
        これを防ぐには、追加ワークツリー側の &lt;code&gt;Properties/launchSettings.json&lt;/code&gt; でポート番号をずらします。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 16px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14px; margin: 15px 0; line-height: 1.6;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;// hotfixワークツリー側の Properties/launchSettings.json&lt;/span&gt;&lt;br/&gt;
        &quot;profiles&quot;: &amp;#123;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&quot;https&quot;: &amp;#123;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;commandName&quot;: &quot;Project&quot;,&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;launchBrowser&quot;: true,&lt;br/&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;applicationUrl&quot;: &quot;https://localhost:7011;http://localhost:5011&quot;, // メイン（7001）と競合しないよう変更！&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;environmentVariables&quot;: &amp;#123;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;ASPNETCORE_ENVIRONMENT&quot;: &quot;Development&quot;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#125;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;#125;&lt;br/&gt;
        &amp;#125;
    &lt;/div&gt;
    &lt;div style=&quot;background: #f0fdf4; border-left: 5px solid #22c55e; padding: 14px 18px; margin: 15px 0; border-radius: 4px; font-size: 15px;&quot;&gt;
        &lt;strong style=&quot;color: #15803d;&quot;&gt;💡 プロの小ワザ:&lt;/strong&gt;&lt;br/&gt;
        &lt;code&gt;launchSettings.json&lt;/code&gt; は開発者個人のローカル設定であるため、コミットしたくない場合は &lt;code&gt;git update-index --assume-unchanged Properties/launchSettings.json&lt;/code&gt; を実行しておけば、変更がステージングに上がってこなくなります。
    &lt;/div&gt;

    &lt;!-- まとめセクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;📌 本日の講義まとめと実践チェックリスト&lt;/h2&gt;
    &lt;p&gt;
        Day 27では、巨大なC#ソリューション開発においてブランチ切り替え待ち時間をゼロにし、並行開発を爆速化する &lt;code&gt;git worktree&lt;/code&gt; の真髄を学びました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 2px solid #e2e8f0; border-radius: 8px; padding: 22px; margin: 25px 0;&quot;&gt;
        &lt;strong style=&quot;color: #1e293b; font-size: 17.5px;&quot;&gt;📋 git worktree 実践チェックリスト&lt;/strong&gt;
        &lt;div style=&quot;margin-top: 14px; line-height: 1.9;&quot;&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ① 急な割り込みタスク発生時、git switch ではなく git worktree add で別フォルダ展開を選択したか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ② リポジトリ全体を別cloneする無駄（ディスク消費・履歴非同期）を回避できたか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ③ Visual Studio を2つ起動し、bin/obj の再ビルド待ちなしで並行作業を開始できたか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ④ Web APIなどの同時デバッグ時、launchSettings.json のポート重複を回避したか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ⑤ 作業完了後、git worktree remove で安全にフォルダとメタデータをクリーンアップしたか？&lt;/label&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 20px 24px; margin: 35px 0; border: 1px solid #cbd5e1;&quot;&gt;
        &lt;strong style=&quot;color: #0f172a; font-size: 17px;&quot;&gt;🚀 次回【Day 28】予告&lt;/strong&gt;&lt;br/&gt;
        &lt;div style=&quot;margin-top: 8px; color: #334155; line-height: 1.8;&quot;&gt;
            第6部「プロの調査・保守・作業効率化テクニック」第2弾！&lt;br/&gt;
            次回のテーマは&lt;strong&gt;【Day 28：git add -p で必要な行だけを綺麗にコミットする部分ステージング技】&lt;/strong&gt;です！&lt;br/&gt;
            1つのC#ファイルの中に「本番用のバグ修正」と「動作確認のために入れた一時デバッグログ（Console.WriteLine）」が混ざってしまったとき、皆さんはどうしていますか？&lt;br/&gt;
            ファイル丸ごとではなく、必要な変更箇所（Hunk）だけを行単位で選別してコミットできるGit屈指のプロ技 &lt;code&gt;git add -p&lt;/code&gt; を徹底解説します！&lt;br/&gt;
            TortoiseGitでの直感的な行単位ステージング操作も合わせて実演しますので、どうぞお楽しみに！
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/8265595291148635780/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-27git-worktree.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/8265595291148635780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/8265595291148635780'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-27git-worktree.html' title='【Day 27】git worktree で再ビルドなしの超高速ブランチ並行開発'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1dol4Vw1RU1wEWHyj77nd1REFPn88ZBWe=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-3488885886762714271</id><published>2026-10-25T09:23:06.597+09:00</published><updated>2026-10-25T09:23:06.597+09:00</updated><title type='text'>【Day 29】バインドマウント（Bind Mount）によるソースコード即時反映（ホットリロード） 〜ホストとコンテナのディレクトリ直結、dotnet watch run による変更検知と自動再起動、WSL2ファイルイベント伝搬の注意点、快適なC#ローカル開発環境の構築〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1-jvwHQK86EGSVX4tlWw9boREV2QxvuWn&quot; alt=&quot;Day 29 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 29: バインドマウント（Bind Mount）によるソースコード即時反映（ホットリロード）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 導入メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: linear-gradient(135deg, #e0f2fe 0%, #f0fdf4 100%); border-left: 6px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0; box-shadow: 0 4px 12px rgba(13,183,237,0.08);&quot;&gt;
        &lt;div style=&quot;font-size: 32px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;font-size: 15.5px; color: #0f172a;&quot;&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; font-weight: bold; color: #0369a1; font-size: 17px;&quot;&gt;「C#コードを1行直すたびに docker compose build するの！？ 待ち時間が長すぎて開発にならないよ！」&lt;/p&gt;
            &lt;p style=&quot;margin: 0; line-height: 1.8;&quot;&gt;
                前回のDay 28では、SQL ServerのDBデータを安全に保護する「Named Volume（名前付きボリューム）」を学びました。&lt;br/&gt;
                しかし、日々のアプリケーション開発現場で同じようにボリュームを扱おうとすると、多くのエンジニアが大きな壁にぶつかります。&lt;br/&gt;
                &lt;strong&gt;「コードを修正するたびに、毎回イメージの再ビルド（&lt;code&gt;docker compose up --build&lt;/code&gt;）を待たなければいけないのか？」&lt;/strong&gt;&lt;br/&gt;
                答えはもちろん &lt;strong&gt;NO&lt;/strong&gt; です！&lt;br/&gt;
                Dockerには、ホストPC上のソースコードフォルダをコンテナ内に直接パイプで繋ぐ &lt;strong&gt;「バインドマウント（Bind Mount）」&lt;/strong&gt; という強力な仕組みが用意されています。&lt;br/&gt;
                さらにC#の &lt;code&gt;dotnet watch&lt;/code&gt; コマンドと組み合わせることで、&lt;strong&gt;「ホストのVisual StudioやVS Codeでコードを保存（Ctrl+S）した瞬間、コンテナ内のアプリがミリ秒で自動更新されるホットリロード環境」&lt;/strong&gt; が実現します！&lt;br/&gt;
                本講義では、バインドマウントの原理、&lt;code&gt;docker-compose.yml&lt;/code&gt; の設定法、そしてWSL2環境で多くの人がハマる「変更検知トラブル」の完全解決策までを徹底解説します！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 目次セクション --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 12px; font-size: 17px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 4px; padding: 2px 8px; font-size: 13px; margin-right: 10px;&quot;&gt;INDEX&lt;/span&gt;
            本日の講義カリキュラム
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #475569; font-size: 15px; line-height: 2;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;第1章: バインドマウント（Bind Mount）の基本原理 〜ホストとコンテナを直結するパイプ〜&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第2章: docker-compose.yml でのバインドマウント記法と「bin/obj上書き問題」の回避策&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第3章: C# / ASP.NET Core の秘密兵器「dotnet watch」とホットリロードの仕組み&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第4章: 実践！Docker Compose ＋ dotnet watch で超高速C#ホットリロード環境を構築する&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第5章: WSL2環境で絶対にハマる「ファイル変更が検知されない」問題の真相とinotify対策&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第6章: 現場での使い分け決定版！「Named Volume」vs「Bind Mount」&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第7章: 本日のまとめと理解度チェッククイズ（次回予告：Day 30 Git管理とVolumeの境界線）&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第1章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第1章: バインドマウント（Bind Mount）の基本原理 〜ホストとコンテナを直結するパイプ〜&lt;/h2&gt;
        &lt;p&gt;
            これまでの講義で学んだ通り、コンテナは通常、Dockerfileの &lt;code&gt;COPY&lt;/code&gt; 命令によってビルド時にイメージ内部へファイルを焼き込みます。&lt;br/&gt;
            そのため、ホストPC上でC#コードを修正しても、コンテナ内のファイルには一切反映されず、再度 &lt;code&gt;docker build&lt;/code&gt; を実行して新しいイメージを作成する必要がありました。
        &lt;/p&gt;
        &lt;p&gt;
            これに対して &lt;strong&gt;「バインドマウント（Bind Mount）」&lt;/strong&gt; とは、&lt;strong&gt;ホストPC上の特定フォルダを、コンテナ内部の特定ディレクトリへ「そのまま直接マウント結合」する技術&lt;/strong&gt; です。
        &lt;/p&gt;
        &lt;p&gt;
            前回のNamed Volumeが「Docker Engineの管理領域（安全な金庫）をコンテナに繋ぐ」ものだったのに対し、バインドマウントは &lt;strong&gt;「開発者が日常的にGitで管理している作業ツリー（./srcなど）をそのままコンテナに露出させる」&lt;/strong&gt; という決定的な違いがあります。
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_29_02_bind_mount_concept.png&quot; alt=&quot;バインドマウントの仕組み&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】ホストPC（./src）とコンテナ環境（/app）の直結構造と双方向同期の仕組み&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;p&gt;
            上図をご覧ください。ホストPC側の &lt;code&gt;./src&lt;/code&gt; フォルダとコンテナ内部の &lt;code&gt;/app&lt;/code&gt; ディレクトリが直結されています。&lt;br/&gt;
            この接続により、以下の劇的なメリットが生まれます：
        &lt;/p&gt;
        &lt;ul style=&quot;line-height: 1.8; color: #334155;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;双方向の完全リアルタイム同期:&lt;/strong&gt; ホスト側のVisual StudioやVS Codeでファイルを保存した瞬間、コンテナ内のファイルも即座に書き換わります。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Gitとの親和性:&lt;/strong&gt; ホスト側のフォルダは通常のGit管理下にあるため、ブランチの切り替えやコミット操作が手元のGitツールでそのまま行えます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;ビルド待ち時間の全廃:&lt;/strong&gt; コードを書き換えるたびに &lt;code&gt;docker build&lt;/code&gt; する数分間のロスタイムが完全にゼロになります。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第2章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第2章: docker-compose.yml でのバインドマウント記法と「bin/obj上書き問題」の回避策&lt;/h2&gt;
        &lt;p&gt;
            バインドマウントを &lt;code&gt;docker-compose.yml&lt;/code&gt; で記述する場合、&lt;code&gt;volumes:&lt;/code&gt; セクションに &lt;strong&gt;「ホストの相対パス : コンテナ内の絶対パス」&lt;/strong&gt; を指定します。
        &lt;/p&gt;
        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 20px 0; overflow-x: auto;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #64748b;&quot;&gt;# docker-compose.yml の基本バインドマウント記法&lt;/span&gt;
&lt;span style=&quot;color: #7dd3fc;&quot;&gt;services:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;webapi:&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;build:&lt;/span&gt;
      &lt;span style=&quot;color: #cbd5e1;&quot;&gt;context:&lt;/span&gt; .
      &lt;span style=&quot;color: #cbd5e1;&quot;&gt;dockerfile:&lt;/span&gt; Dockerfile.dev
    &lt;span style=&quot;color: #f472b6;&quot;&gt;ports:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;5000:5000&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;volumes:&lt;/span&gt;
      &lt;span style=&quot;color: #64748b;&quot;&gt;# ホストの ./src フォルダをコンテナ内の /app/src にバインドマウント&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;./src:/app/src&lt;/span&gt;
&lt;/pre&gt;
        &lt;/div&gt;
        &lt;p&gt;
            しかし、C# / .NET 開発者がここで必ず直面するのが、悪名高い &lt;strong&gt;「ホストとコンテナの bin / obj 衝突問題」&lt;/strong&gt; です！
        &lt;/p&gt;

        &lt;div style=&quot;background: #fff1f2; border-left: 6px solid #e11d48; border-radius: 6px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
            &lt;h4 style=&quot;margin: 0 0 8px 0; color: #be123c; font-size: 16px;&quot;&gt;⚠️ C#エンジニア必読：bin / obj 衝突の罠&lt;/h4&gt;
            &lt;p style=&quot;margin: 0; font-size: 14.5px; line-height: 1.8; color: #4c0519;&quot;&gt;
                ホストPC（Windows）でVisual Studioを開いていると、Windows用のバイナリが &lt;code&gt;bin/&lt;/code&gt; や &lt;code&gt;obj/&lt;/code&gt; にビルドされます。&lt;br/&gt;
                これをそのままLinuxコンテナに丸ごとバインドマウント（&lt;code&gt;.:/app&lt;/code&gt;）してしまうと、&lt;strong&gt;Windows用のDLLやビルドキャッシュがコンテナ内のLinuxランタイムと衝突し、ビルドエラーや不可解な例外でアプリが起動しなくなります！&lt;/strong&gt;
            &lt;/p&gt;
        &lt;/div&gt;

        &lt;p&gt;
            この問題をエレガントに解決するプロの技法が、&lt;strong&gt;「匿名ボリューム（Anonymous Volume）によるマスキング」&lt;/strong&gt; です：
        &lt;/p&gt;
        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-family: Consolas, Monaco, monospace; font-size: 14px; margin: 20px 0; overflow-x: auto;&quot;&gt;
&lt;pre style=&quot;margin: 0; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #64748b;&quot;&gt;# bin / obj の衝突を回避する黄金のボリューム定義&lt;/span&gt;
&lt;span style=&quot;color: #7dd3fc;&quot;&gt;services:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;webapi:&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;volumes:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;.:/app&lt;/span&gt;              &lt;span style=&quot;color: #64748b;&quot;&gt;# ソースコード全体をマウント&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;/app/bin&lt;/span&gt;            &lt;span style=&quot;color: #64748b;&quot;&gt;# コンテナ内の bin を独立ボリュームで保護（ホストで上書きさせない）&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;/app/obj&lt;/span&gt;            &lt;span style=&quot;color: #64748b;&quot;&gt;# コンテナ内の obj を独立ボリュームで保護&lt;/span&gt;
&lt;/pre&gt;
        &lt;/div&gt;
        &lt;p&gt;
            Dockerはマウントパスが重複する場合、「より深い階層のマウントを優先する」という仕様を持っています。&lt;br/&gt;
            上記のように &lt;code&gt;/app/bin&lt;/code&gt; と &lt;code&gt;/app/obj&lt;/code&gt; をコロンなしの「匿名ボリューム」として指定することで、&lt;strong&gt;ソースコード（.csファイル等）はホストと直結されつつ、ビルド生成物（bin/obj）はLinuxコンテナ独自の専用領域に隔離される&lt;/strong&gt; のです！
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第3章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第3章: C# / ASP.NET Core の秘密兵器「dotnet watch」とホットリロードの仕組み&lt;/h2&gt;
        &lt;p&gt;
            ファイルをバインドマウントしただけでは、コンテナ内のプロセスは起動時の古いDLLを実行し続けてしまいます。&lt;br/&gt;
            そこで登場するのが、.NET CLIに標準搭載されている &lt;strong&gt;&lt;code&gt;dotnet watch&lt;/code&gt;&lt;/strong&gt; コマンドです！
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_29_03_hot_reload_flow.png&quot; alt=&quot;ホットリロードの3ステップ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】dotnet watch によるホットリロードの3ステップ（編集保存 ➡ 変更検知 ➡ 差分自動反映）&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;p&gt;
            &lt;code&gt;dotnet watch&lt;/code&gt; は、指定したディレクトリ内のファイルシステム監視イベントを常時リッスンします。&lt;br/&gt;
            上図の3ステップの流れをご覧ください：
        &lt;/p&gt;
        &lt;ol style=&quot;line-height: 1.9; color: #334155;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;Step 1: ホスト側でコード編集＆保存:&lt;/strong&gt; 開発者がVisual StudioやVS CodeでC#コードを修正し、保存（Ctrl+S）します。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Step 2: バインドマウント経由で変更検知:&lt;/strong&gt; ホストOSのファイル更新がバインドマウントを通じて即座にコンテナ内のLinuxカーネルに通知されます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Step 3: 差分のみ自動反映（ホットリロード）:&lt;/strong&gt; &lt;code&gt;dotnet watch&lt;/code&gt; が変更を検知し、メソッドの追加やロジック変更であれば &lt;strong&gt;「プロセスを再起動することなく、実行中メモリ内のILコードを瞬時に差し替え（ホットリロード）」&lt;/strong&gt; します！&lt;/li&gt;
        &lt;/ol&gt;
        &lt;p&gt;
            構造の大きな変更（クラスの継承関係変更やプロジェクトファイルの変更など）が発生した場合でも、&lt;code&gt;dotnet watch&lt;/code&gt; が自動的にプロセスを再起動（Restart）してくれるため、開発者がターミナルに触る必要は一切ありません。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第4章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第4章: 実践！Docker Compose ＋ dotnet watch で超高速C#ホットリロード環境を構築する&lt;/h2&gt;
        &lt;p&gt;
            それでは、実際に現場で使える完全な設定ファイルを見ていきましょう。&lt;br/&gt;
            本番用Dockerfile（軽量なaspnetランタイムを使用）とは別に、開発専用の &lt;code&gt;Dockerfile.dev&lt;/code&gt; を用意するのがベストプラクティスです。なぜなら、ホットリロードを実行するには &lt;strong&gt;.NET SDK&lt;/strong&gt; が必要だからです。
        &lt;/p&gt;

        &lt;div style=&quot;background: #0f172a; border-radius: 8px; margin: 20px 0; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.15);&quot;&gt;
            &lt;div style=&quot;background: #1e293b; padding: 10px 16px; color: #94a3b8; font-size: 13px; font-weight: bold; border-bottom: 1px solid #334155;&quot;&gt;
                📄 Dockerfile.dev（開発専用・SDK搭載イメージ）
            &lt;/div&gt;
            &lt;pre style=&quot;margin: 0; padding: 18px 20px; color: #f8fafc; font-family: Consolas, Monaco, monospace; font-size: 14px; line-height: 1.6; overflow-x: auto;&quot;&gt;&lt;span style=&quot;color: #64748b;&quot;&gt;# ホットリロードにはコンパイル機能が必要なため SDK イメージを使用&lt;/span&gt;
&lt;span style=&quot;color: #f472b6;&quot;&gt;FROM&lt;/span&gt; mcr.microsoft.com/dotnet/sdk:8.0 AS dev
&lt;span style=&quot;color: #f472b6;&quot;&gt;WORKDIR&lt;/span&gt; /app

&lt;span style=&quot;color: #64748b;&quot;&gt;# 依存関係（.csproj）を先にコピーしてリストア（キャッシュ活用）&lt;/span&gt;
&lt;span style=&quot;color: #f472b6;&quot;&gt;COPY&lt;/span&gt; *.csproj ./
&lt;span style=&quot;color: #f472b6;&quot;&gt;RUN&lt;/span&gt; dotnet restore

&lt;span style=&quot;color: #64748b;&quot;&gt;# ソースコード全体をコピー（初回ビルド用）&lt;/span&gt;
&lt;span style=&quot;color: #f472b6;&quot;&gt;COPY&lt;/span&gt; . ./

&lt;span style=&quot;color: #64748b;&quot;&gt;# ASP.NET Core のリッスンURLを設定&lt;/span&gt;
&lt;span style=&quot;color: #f472b6;&quot;&gt;ENV&lt;/span&gt; ASPNETCORE_URLS=http://+:5000
&lt;span style=&quot;color: #f472b6;&quot;&gt;ENV&lt;/span&gt; ASPNETCORE_ENVIRONMENT=Development

&lt;span style=&quot;color: #64748b;&quot;&gt;# dotnet watch run でコンテナを起動！&lt;/span&gt;
&lt;span style=&quot;color: #f472b6;&quot;&gt;ENTRYPOINT&lt;/span&gt; [&lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;dotnet&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;watch&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;run&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;--non-interactive&quot;&lt;/span&gt;]&lt;/pre&gt;
        &lt;/div&gt;

        &lt;p&gt;
            続いて、&lt;code&gt;docker-compose.yml&lt;/code&gt; です：
        &lt;/p&gt;

        &lt;div style=&quot;background: #0f172a; border-radius: 8px; margin: 20px 0; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.15);&quot;&gt;
            &lt;div style=&quot;background: #1e293b; padding: 10px 16px; color: #94a3b8; font-size: 13px; font-weight: bold; border-bottom: 1px solid #334155;&quot;&gt;
                📄 docker-compose.yml（バインドマウント＆ポーリング設定）
            &lt;/div&gt;
            &lt;pre style=&quot;margin: 0; padding: 18px 20px; color: #f8fafc; font-family: Consolas, Monaco, monospace; font-size: 14px; line-height: 1.6; overflow-x: auto;&quot;&gt;&lt;span style=&quot;color: #7dd3fc;&quot;&gt;services:&lt;/span&gt;
  &lt;span style=&quot;color: #38bdf8;&quot;&gt;csharp-api:&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;build:&lt;/span&gt;
      &lt;span style=&quot;color: #cbd5e1;&quot;&gt;context:&lt;/span&gt; .
      &lt;span style=&quot;color: #cbd5e1;&quot;&gt;dockerfile:&lt;/span&gt; Dockerfile.dev
    &lt;span style=&quot;color: #f472b6;&quot;&gt;ports:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;&quot;5000:5000&quot;&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;environment:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;DOTNET_USE_POLLING_FILE_WATCHER=true&lt;/span&gt;  &lt;span style=&quot;color: #64748b;&quot;&gt;# ← ファイル変更検知の安定化キー！&lt;/span&gt;
    &lt;span style=&quot;color: #f472b6;&quot;&gt;volumes:&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;.:/app&lt;/span&gt;              &lt;span style=&quot;color: #64748b;&quot;&gt;# ホストのコードをコンテナに直結&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;/app/bin&lt;/span&gt;            &lt;span style=&quot;color: #64748b;&quot;&gt;# binの衝突防止&lt;/span&gt;
      - &lt;span style=&quot;color: #a5f3fc;&quot;&gt;/app/obj&lt;/span&gt;            &lt;span style=&quot;color: #64748b;&quot;&gt;# objの衝突防止&lt;/span&gt;
&lt;/pre&gt;
        &lt;/div&gt;

        &lt;p&gt;
            これで準備完了です！ターミナルから以下のコマンドを実行してみましょう：
        &lt;/p&gt;
        &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14px;&quot;&gt;
            $ docker compose up
        &lt;/div&gt;
        &lt;p&gt;
            起動後、ブラウザで &lt;code&gt;http://localhost:5000/weatherforecast&lt;/code&gt; にアクセスします。&lt;br/&gt;
            その後、手元のIDEでコントローラー内の返却文字列を少し書き換えて保存（Ctrl+S）してみてください。&lt;br/&gt;
            ターミナル上に &lt;code&gt;Hot reload succeeded in 82 ms.&lt;/code&gt; と表示され、ブラウザをF5リロードするだけで新ロジックが即座に反映されるはずです！
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第5章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第5章: WSL2環境で絶対にハマる「ファイル変更が検知されない」問題の真相とinotify対策&lt;/h2&gt;
        &lt;p&gt;
            Windows 11 ＋ WSL2環境でDockerを使っているエンジニアが、ほぼ100%と言っていい確率でハマる &lt;strong&gt;「魔の落とし穴」&lt;/strong&gt; があります。&lt;br/&gt;
            それは、&lt;strong&gt;「コードを保存したのに、コンテナ内の dotnet watch がうんともすんとも言わない（変更を検知しない）」&lt;/strong&gt; という現象です！
        &lt;/p&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_29_04_wsl2_performance.png&quot; alt=&quot;WSL2環境での配置対比&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】WSL2環境におけるプロジェクト配置対比（Linux領域の爆速inotify vs Windows領域の遅延）&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;p&gt;
            この原因は、&lt;strong&gt;「プロジェクトファイルをWindows領域（Cドライブ直下など）に配置していること」&lt;/strong&gt; にあります。&lt;br/&gt;
            上図の対比をご覧ください：
        &lt;/p&gt;
        &lt;div style=&quot;display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin: 20px 0;&quot;&gt;
            &lt;div style=&quot;background: #f0fdf4; border: 1px solid #86efac; border-radius: 8px; padding: 16px;&quot;&gt;
                &lt;h4 style=&quot;color: #166534; margin: 0 0 8px 0; font-size: 15.5px;&quot;&gt;🐧 Linux領域（超推奨：wsl$\...）&lt;/h4&gt;
                &lt;ul style=&quot;margin: 0; padding-left: 18px; font-size: 14px; line-height: 1.7; color: #14532d;&quot;&gt;
                    &lt;li&gt;配置先: &lt;code&gt;/home/username/projects/...&lt;/code&gt;&lt;/li&gt;
                    &lt;li&gt;Linuxネイティブの &lt;code&gt;inotify&lt;/code&gt; イベントが即座にDocker Engineへ到達。&lt;/li&gt;
                    &lt;li&gt;ファイルI/O速度がWindows領域の約5倍〜10倍高速！&lt;/li&gt;
                    &lt;li&gt;ホットリロードが100%確実に瞬時動作。&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
            &lt;div style=&quot;background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; padding: 16px;&quot;&gt;
                &lt;h4 style=&quot;color: #991b1b; margin: 0 0 8px 0; font-size: 15.5px;&quot;&gt;🐢 Windows領域（非推奨：/mnt/c/...）&lt;/h4&gt;
                &lt;ul style=&quot;margin: 0; padding-left: 18px; font-size: 14px; line-height: 1.7; color: #7f1d1d;&quot;&gt;
                    &lt;li&gt;配置先: &lt;code&gt;C:Users
ame\projects\...&lt;/code&gt;&lt;/li&gt;
                    &lt;li&gt;9Pプロトコル経由のため、Windowsのファイル更新イベントがWSL2内で欠落・遅延する。&lt;/li&gt;
                    &lt;li&gt;OS境界をまたぐためディスクI/Oが著しく低速。&lt;/li&gt;
                    &lt;li&gt;ホットリロードが反応しないトラブルが多発！&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        &lt;/div&gt;

        &lt;div style=&quot;background: #f8fafc; border: 2px solid #10b981; border-radius: 8px; padding: 18px 20px; margin: 20px 0;&quot;&gt;
            &lt;h4 style=&quot;margin: 0 0 8px 0; color: #047857; font-size: 16px;&quot;&gt;💡 もしどうしてもCドライブ配下で開発したい場合の特効薬&lt;/h4&gt;
            &lt;p style=&quot;margin: 0; font-size: 14.5px; line-height: 1.8; color: #064e3b;&quot;&gt;
                会社の制約等でプロジェクトをWindowsファイルシステム上に置かざるを得ない場合は、前章の環境変数：&lt;br/&gt;
                &lt;code&gt;DOTNET_USE_POLLING_FILE_WATCHER=true&lt;/code&gt;&lt;br/&gt;
                を必ず設定してください。OSのイベント通知に頼る代わりに、.NET自身が一定間隔でファイル差分をポーリング監視（確認）するため、Cドライブ上でも確実に変更を検知できるようになります！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 第6章 --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第6章: 現場での使い分け決定版！「Named Volume」vs「Bind Mount」&lt;/h2&gt;
        &lt;p&gt;
            第6部で学んだ2大ストレージ機能、「Named Volume」と「Bind Mount」。&lt;br/&gt;
            現場でどちらを使うべきか迷ったら、以下の &lt;strong&gt;「3大黄金基準」&lt;/strong&gt; で判断してください：
        &lt;/p&gt;

        &lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0; font-size: 14.5px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #0f172a; color: #ffffff;&quot;&gt;
                    &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #334155;&quot;&gt;機能&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #334155;&quot;&gt;主な用途&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #334155;&quot;&gt;アクセス元&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #334155;&quot;&gt;パフォーマンス＆権限&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; font-weight: bold; color: #0284c7;&quot;&gt;Named Volume&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;SQL Server / PostgreSQL / Redis などの永続データ&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;コンテナのみ（ホストからは不可視）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;最高速（Ext4）。権限競合なし。安全保護。&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; font-weight: bold; color: #7c3aed;&quot;&gt;Bind Mount&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;C#ソースコード、設定ファイル（appsettings等）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;ホストのIDE ＋ コンテナの双方&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;ホスト依存。ホットリロード・即時同期用。&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;

        
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_29_05_csharp_iteration.png&quot; alt=&quot;C#開発現場での劇的進化&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】C#開発現場における劇的進化（再ビルド待ち時間ゼロ化による快適イテレーション）&lt;/div&gt;
    &lt;/div&gt;
    

        &lt;p&gt;
            上図の通り、現代のDocker × C#開発現場では、&lt;strong&gt;「データベースにはNamed Volumeをあてがい、アプリケーションコードにはBind Mountを適用する」&lt;/strong&gt; というハイブリッド構成がデファクトスタンダードです。&lt;br/&gt;
            これにより、DBのレコードは安全に守られつつ、アプリコードは保存即リロードという、究極の快適開発環境が手に入ります！
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第7章: まとめ＆クイズ --&gt;
    &lt;div style=&quot;margin: 40px 0;&quot;&gt;
        &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; font-size: 22px;&quot;&gt;第7章: 本日のまとめと理解度チェッククイズ&lt;/h2&gt;

        &lt;!-- まとめボックス --&gt;
        &lt;div style=&quot;background: #f8fafc; border: 2px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0;&quot;&gt;
            &lt;h3 style=&quot;color: #0369a1; margin-top: 0; font-size: 18px;&quot;&gt;📌 本日の最重要チェックポイント&lt;/h3&gt;
            &lt;ol style=&quot;margin: 0; padding-left: 22px; line-height: 2; color: #334155; font-size: 15.5px;&quot;&gt;
                &lt;li&gt;&lt;strong&gt;バインドマウントはホストフォルダの直結パイプ:&lt;/strong&gt; &lt;code&gt;COPY&lt;/code&gt; による再ビルド不要で、手元のIDEの編集がコンテナへ即時反映。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;C#のホットリロードは &lt;code&gt;dotnet watch&lt;/code&gt; で実現:&lt;/strong&gt; 差分ILコードの差し替えにより、コンテナ再起動なしでミリ秒更新。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;&lt;code&gt;bin/obj&lt;/code&gt; は匿名ボリュームで必ず隔離:&lt;/strong&gt; ホスト（Windows）とコンテナ（Linux）のバイナリ衝突を防ぐ必須テクニック。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;WSL2ではプロジェクトをLinux領域に置くのが鉄則:&lt;/strong&gt; &lt;code&gt;wsl$Ubuntu\...&lt;/code&gt; 配下に置くことで &lt;code&gt;inotify&lt;/code&gt; が高速伝搬。&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;コードはバインドマウント、データはNamed Volume:&lt;/strong&gt; 役割に応じた適切な使い分けがプロの現場設計。&lt;/li&gt;
            &lt;/ol&gt;
        &lt;/div&gt;

        &lt;!-- 理解度チェッククイズ --&gt;
        &lt;div style=&quot;background: #ffffff; border: 1px solid #cbd5e1; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
            &lt;h3 style=&quot;color: #0f172a; margin-top: 0; font-size: 17px;&quot;&gt;🎯 理解度チェッククイズ&lt;/h3&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; color: #475569; font-weight: bold;&quot;&gt;Q: Windows 11上でDocker Composeと dotnet watch を用いてC#開発を行う際、コードを保存してもホットリロードが反応しない場合の対策として、最も適切なものはどれでしょうか？&lt;/p&gt;
            &lt;ul style=&quot;margin: 0 0 15px 0; padding-left: 20px; color: #334155; line-height: 1.8;&quot;&gt;
                &lt;li&gt;A. コンテナを特権モード（&lt;code&gt;privileged: true&lt;/code&gt;）で起動する&lt;/li&gt;
                &lt;li&gt;B. プロジェクトをLinux領域（&lt;code&gt;wsl$\...&lt;/code&gt;）に移動するか、環境変数 &lt;code&gt;DOTNET_USE_POLLING_FILE_WATCHER=true&lt;/code&gt; を設定する&lt;/li&gt;
                &lt;li&gt;C. Dockerfile で &lt;code&gt;USER root&lt;/code&gt; を指定して実行権限を最大化する&lt;/li&gt;
                &lt;li&gt;D. &lt;code&gt;dotnet watch&lt;/code&gt; ではなく &lt;code&gt;dotnet run&lt;/code&gt; を使用する&lt;/li&gt;
            &lt;/ul&gt;
            &lt;details style=&quot;background: #f1f5f9; padding: 12px 16px; border-radius: 6px; cursor: pointer;&quot;&gt;
                &lt;summary style=&quot;font-weight: bold; color: #0284c7;&quot;&gt;正解と解説を見る&lt;/summary&gt;
                &lt;p style=&quot;margin: 10px 0 0 0; color: #0f172a; line-height: 1.8;&quot;&gt;
                    &lt;strong&gt;正解: B&lt;/strong&gt;&lt;br/&gt;
                    WindowsのNTFS領域（&lt;code&gt;/mnt/c/&lt;/code&gt;）からWSL2へのファイル変更イベント（inotify）は遅延や欠落が発生しやすいため、ネイティブLinuxファイルシステム領域（&lt;code&gt;wsl$\...&lt;/code&gt;）にプロジェクトを配置することが最も根本的な解決策です。また、設定で &lt;code&gt;DOTNET_USE_POLLING_FILE_WATCHER=true&lt;/code&gt; を有効にすることで、ポーリング方式により確実に変更が検知されるようになります。
                &lt;/p&gt;
            &lt;/details&gt;
        &lt;/div&gt;

        &lt;!-- 次回予告 --&gt;
        &lt;div style=&quot;background: linear-gradient(135deg, #fdf4ff 0%, #fae8ff 100%); border-left: 6px solid #c026d3; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
            &lt;h3 style=&quot;color: #86198f; margin-top: 0; font-size: 17px;&quot;&gt;🚀 次回予告（Day 30）&lt;/h3&gt;
            &lt;p style=&quot;margin: 0; color: #701a75; line-height: 1.8;&quot;&gt;
                次回は第6部の総決算！&lt;strong&gt;「Git管理すべきファイルとVolumeに任せるデータの境界線」&lt;/strong&gt; を徹底解説します！&lt;br/&gt;
                Gitにコミットすべき設定ファイル、&lt;code&gt;.gitignore&lt;/code&gt; で除外すべきデータ、そしてVolumeで永続化すべきデータベースの境界線を、C#開発現場の実例をもとに完璧に整理します。お楽しみに！
            &lt;/p&gt;
        &lt;/div&gt;

    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/3488885886762714271/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-29bind-mount-dotnet-watch-run-wsl2c.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3488885886762714271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3488885886762714271'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-29bind-mount-dotnet-watch-run-wsl2c.html' title='【Day 29】バインドマウント（Bind Mount）によるソースコード即時反映（ホットリロード） 〜ホストとコンテナのディレクトリ直結、dotnet watch run による変更検知と自動再起動、WSL2ファイルイベント伝搬の注意点、快適なC#ローカル開発環境の構築〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1-jvwHQK86EGSVX4tlWw9boREV2QxvuWn=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-4150710332640774145</id><published>2026-10-24T18:09:16.088+09:00</published><updated>2026-10-24T18:09:16.088+09:00</updated><title type='text'>【Day 26】【Case 6】AIエージェントを活用したケーススタディ自動実行</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1h6tMOqi7YGXXXTsdsGkK7IBu070nT1s5&quot; alt=&quot;Day 26 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 26】AIエージェント併用ケーススタディ（実務応用）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 25では、急な仕様変更や機能リリース順序の入れ替えにスマートに対応する「チェリーピック（git cherry-pick）」の実践テクニックを学びました。&lt;br/&gt;
            本日のDay 26は、第5部「開発フェーズ別・現場ケーススタディ」の集大成として、現代のソフトウェア開発を根底から変革しつつある最先端テーマ——&lt;strong&gt;【AIエージェントを活用したケーススタディ自動実行（Issue-to-PR）】&lt;/strong&gt;を徹底解説します！&lt;br/&gt;
            いま、ソフトウェア開発の現場では &lt;strong&gt;Google Antigravity&lt;/strong&gt; や &lt;strong&gt;Claude Code&lt;/strong&gt; といった自律型AIコーディングエージェントの導入が急速に進んでいます。&lt;br/&gt;
            かつてエンジニアが手作業で行っていた「チケット確認・ブランチ作成・ソース調査・コード修正・単体テスト実行・プルリクエスト作成」という一連の定型業務は、いまや&lt;strong&gt;『Issue #101 のバグ修正用ブランチを切り、修正してPRを作って』&lt;/strong&gt;とプロンプトで一括指示するだけで、AIがターミナルとGitを操作して自律的に完走できるようになりました。&lt;br/&gt;
            「AIにコードを書かせたら、思わぬバグが混入したりブランチが壊れたりしないのか？」「Gitのブランチ戦略やテスト自動化とどう組み合わせれば安全なのか？」と疑問に思う方も多いでしょう。&lt;br/&gt;
            本日は、C#現場で頻発する &lt;code&gt;NullReferenceException&lt;/code&gt; の障害Issueを題材に、AIエージェントによる「自律ブランチ作成からプルリク起票まで」の完全シミュレーションをお見せします！&lt;br/&gt;
            さらに、AIが90%の定型作業を高速代行する時代において、&lt;strong&gt;人間のエンジニアが担うべき『最終コードレビューとマージ承認の絶対原則』&lt;/strong&gt;まで、実践的なプロの技術を分かりやすくお伝えします！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        AIコーディングアシスタントは、「コードの自動補完」から「自律的な課題解決（Agentic Workflow）」の段階へ進化しました。&lt;br/&gt;
        GitHub Issueの障害チケットを読み込み、専用ブランチをチェックアウトし、プロジェクト全体を検索して原因コードを特定し、C#コードを修正して &lt;code&gt;dotnet test&lt;/code&gt; で検証し、GitHub CLI (&lt;code&gt;gh&lt;/code&gt;) でプルリクエスト（PR）を自動起票する——この&lt;strong&gt;「Issue-to-PR」&lt;/strong&gt;の流れを理解し、手足のように使いこなすことが次世代エンジニアの必須スキルです。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;従来の手作業による定型開発と、AIエージェント（Antigravity / Claude Code）による自律代行の違いを理解する&lt;/li&gt;
            &lt;li&gt;「Issue解析 → ブランチ自律作成 → コード修正・テスト → PR自動起票」の3ステップワークフローを習得する&lt;/li&gt;
            &lt;li&gt;C#プロジェクトにおいて、障害チケット（NullReferenceException）をAIに自律修正させ、&lt;code&gt;dotnet test&lt;/code&gt; で品質担保する実戦手順を把握する&lt;/li&gt;
            &lt;li&gt;GitHub CLI（&lt;code&gt;gh pr create&lt;/code&gt;）とAIエージェントの連携による高品質なPR説明文自動生成の仕組みを理解する&lt;/li&gt;
            &lt;li&gt;AI生成コードに対する「人間の3大レビュー観点（設計意図・セキュリティ・業務要件）」とマージ承認の絶対原則を身につける&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: 従来の手作業 vs AIエージェント自律開発 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】従来の手動作業 vs AIエージェント自律開発：定型タスクからの劇的解放&lt;/h2&gt;
    &lt;p&gt;
        まず、エンジニアがこれまで日常的に行ってきた「バグ修正の手順」と、AIエージェント導入後の手順を比較してみましょう。
    &lt;/p&gt;

    &lt;!-- 図解① --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/129BrVo4gzoGqbDDEI6mWYCfQGvVhOzUb&quot; alt=&quot;従来の手作業開発 vs AIエージェント自律開発&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】人間が全ステップをこなして疲弊する旧時代の手作業 vs 1行指示で自律完走するAIエージェント開発&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        Subversion (SVN) の時代や初期のGit運用では、バグ修正ひとつ対応するにも多くの手作業が存在していました。&lt;br/&gt;
        チケット管理システム（Redmine、Jira、GitHub Issues）を開いて内容を確認し、ターミナルで命名規則に従ってブランチを切り、エディタで関連ファイルを探し出し、修正を加え、ローカルビルドとテストを回し、ブラウザでPR作成画面を開いてチケット番号や変更理由を手打ちする……。&lt;br/&gt;
        これらの一連の作業は、1回あたり30分〜1時間以上の時間を奪い、チケット番号の入力ミスやテスト忘れといったヒューマンエラーの原因にもなっていました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #fff1f2; border-left: 5px solid #e11d48; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #be123c; font-size: 16.5px;&quot;&gt;💥 手作業中心の開発現場で発生しがちな問題&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85; color: #4c0519;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;コンテキストスイッチの消耗:&lt;/strong&gt; チケット確認、IDE、ターミナル、ブラウザの間を何度も往復し、集中力が途切れる。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;テスト実行の見落とし:&lt;/strong&gt; 「たった1行のnullチェック修正だから」と油断してテストを省略し、別の箇所で副作用デグレが発生する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;PR説明文の形骸化:&lt;/strong&gt; 修正作業で力尽き、PRの説明に「修正しました」と1行しか書かれず、後からのレビュアーの負担が増大する。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        これに対し、最新のAIエージェント（Antigravity / Claude Code）は、ターミナル実行権限とファイル編集能力を持っています。&lt;br/&gt;
        エンジニアが&lt;strong&gt;「Issue #101 のバグを調査して修正し、テストを実行してPRを作成して」&lt;/strong&gt;と1行指示するだけで、チケット情報の取得からブランチ作成、コード修正、自動テスト実行、そしてConventional Commitsに準拠したコミットとPR起票までを&lt;strong&gt;完全自律（Autonomous）&lt;/strong&gt;で駆け抜けます！
    &lt;/p&gt;

    &lt;!-- セクション③: Issue-to-PR 自動化の3ステップ完全手順 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】AIによる「Issue-to-PR」自律実行の3ステップ完全手順&lt;/h2&gt;
    &lt;p&gt;
        AIエージェントが内部でどのようにGitと連携し、プルリクエストまでたどり着くのか、その3ステップを可視化しました。
    &lt;/p&gt;

    &lt;!-- 図解② --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1L9kKT_76WjjvklrPx5TYA-h8eobF8Rkg&quot; alt=&quot;AIによるIssue-to-PR自動化の3ステップ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】Issue解析・コード修正＆テスト検証・PR自動起票の3ステップ完全フロー&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;ステップ1: Issueの自動解析と専用ブランチの自律作成&lt;/h3&gt;
    &lt;p&gt;
        AIエージェントはGitHub CLI（&lt;code&gt;gh issue view 101&lt;/code&gt;）やリポジトリ内のドキュメントから障害内容を読み取り、適切な命名規則（例: &lt;code&gt;fix/issue-101-null-check&lt;/code&gt;）で自動的にトピックブランチを作成します。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# AIが内部で自動実行するコマンド例&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch main&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; pull origin main&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch -c fix/issue-101-null-customer-address
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;ステップ2: C#コードのピンポイント修正とdotnet test自動検証&lt;/h3&gt;
    &lt;p&gt;
        スタックトレースやエラーログから原因箇所を特定し、最小限かつ安全な修正を実施します。修正後、必ず &lt;code&gt;dotnet test&lt;/code&gt; を実行して既存テストが破損していないことを検証します。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# AIが自動でテスト実行＆合否判定&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;dotnet&lt;/span&gt; test --logger &quot;console;verbosity=normal&quot;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;合格! - 失敗: 0、合格: 28、スキップ: 0、合計: 28、期間: 1.2s&lt;/span&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;ステップ3: コミットとGitHub CLIによるPR自動起票&lt;/h3&gt;
    &lt;p&gt;
        テスト合格を確認したAIは、変更差分をステージングしてコミットメッセージを作成し、リモートへプッシュしてGitHub PRを起票します。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# コミット＆プッシュ＆PR起票&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; commit -m &quot;fix(payment): prevent NullReferenceException when customer address is null (fixes #101)&quot;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push -u origin fix/issue-101-null-customer-address&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;gh&lt;/span&gt; pr create --title &quot;fix: 顧客住所未登録時の決済エラー修正 (#101)&quot; --body &quot;## 概要
Issue #101 のNullReferenceExceptionを修正しました。

## 変更点
- Customer.AddressのNull条件演算子チェックを追加
- 単体テストケースを追加&quot;
    &lt;/div&gt;

    &lt;!-- セクション④: C#現場での実戦例 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【実戦C#編】Issue #101「NullReferenceException」のAI自律解決シミュレーション&lt;/h2&gt;
    &lt;p&gt;
        それでは、実際のC# Web APIプロジェクトにおける具体的な障害対応シミュレーションを見てみましょう。
    &lt;/p&gt;

    &lt;!-- 図解③ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1RlZMG_REqdxoRbha1iGaRpB0JBqZw9iA&quot; alt=&quot;C#現場でのバグ修正とdotnet test自動検証&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】C#現場での障害チケット解決例（NullReferenceException修正とdotnet testによる全件合格検証）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; margin-top: 25px; font-size: 18px;&quot;&gt;障害チケットの内容（Issue #101）&lt;/h3&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 6px; padding: 18px; margin: 15px 0;&quot;&gt;
        &lt;strong style=&quot;color: #e11d48; font-size: 16px;&quot;&gt;🚨 [Bug] ゲスト購入時の決済処理で 500 Internal Server Error 発生&lt;/strong&gt;
        &lt;p style=&quot;margin: 8px 0; font-size: 14.5px; color: #475569;&quot;&gt;
            &lt;strong&gt;再現手順:&lt;/strong&gt; 住所登録をスキップしたゲストユーザーが決済API（POST /api/payments）を呼び出す。&lt;br/&gt;
            &lt;strong&gt;スタックトレース:&lt;/strong&gt;&lt;br/&gt;
            &lt;code&gt;System.NullReferenceException: Object reference not set to an instance of an object.&lt;/code&gt;&lt;br/&gt;
            &lt;code&gt;   at MyApp.Services.PaymentProcessor.CalculateTax(Customer customer) in PaymentProcessor.cs:line 42&lt;/code&gt;
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 25px; font-size: 18px;&quot;&gt;AIエージェントへの指示プロンプト（プロの実践例）&lt;/h3&gt;
    &lt;div style=&quot;background: #1e1e38; color: #f1f5f9; padding: 18px; border-radius: 6px; font-size: 14.5px; margin: 15px 0; border-left: 5px solid #a855f7;&quot;&gt;
        &lt;span style=&quot;color: #c084fc; font-weight: bold;&quot;&gt;【エンジニアのプロンプト入力】&lt;/span&gt;&lt;br/&gt;
        「GitHub Issue #101 を確認してください。ゲスト購入時に PaymentProcessor.cs で NullReferenceException が発生している問題です。&lt;br/&gt;
        1. &lt;code&gt;fix/issue-101-null-address&lt;/code&gt; ブランチを新設してください。&lt;br/&gt;
        2. 原因箇所をC#のNull許容参照型およびNull条件演算子を用いて安全に修正してください。&lt;br/&gt;
        3. 再現テストケースを &lt;code&gt;PaymentProcessorTests.cs&lt;/code&gt; に追加し、&lt;code&gt;dotnet test&lt;/code&gt; で全件パスすることを確認してください。&lt;br/&gt;
        4. テスト合格後、コミットしてGitHub CLIでPRを作成してください。」
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 25px; font-size: 18px;&quot;&gt;AIが自動生成した修正C#コード&lt;/h3&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 16px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14px; margin: 15px 0; line-height: 1.6;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;// 修正前: customer.Address が null の場合にクラッシュ！&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #f87171;&quot;&gt;- decimal taxRate = GetTaxRateByZipCode(customer.Address.ZipCode);&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;// 修正後: C# 8.0+ Null条件演算子とNull合体演算子で安全にフォールバック&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;+ string? zipCode = customer?.Address?.ZipCode;&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;+ decimal taxRate = string.IsNullOrWhiteSpace(zipCode)&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;+     ? DefaultStandardTaxRate&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;+     : GetTaxRateByZipCode(zipCode);&lt;/span&gt;
    &lt;/div&gt;

    &lt;p&gt;
        AIは既存のビジネスロジックを破壊することなく、住所が未登録の場合は標準税率（&lt;code&gt;DefaultStandardTaxRate&lt;/code&gt;）へ安全にフォールバックするコードを実装しました。&lt;br/&gt;
        さらに、&lt;code&gt;PaymentProcessorTests.cs&lt;/code&gt; に &lt;code&gt;CalculateTax_WhenAddressIsNull_ReturnsDefaultTaxRate()&lt;/code&gt; という単体テストを自動追加し、&lt;code&gt;dotnet test&lt;/code&gt; で100%成功を確認してPRを立ち上げました。
    &lt;/p&gt;

    &lt;!-- セクション⑤: 人間とAIの役割分担 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【図解】人間とAIの役割分担：AIが下準備（90%）、人間が意思決定（10%）&lt;/h2&gt;
    &lt;p&gt;
        「AIがPRまで作ってくれるなら、人間のエンジニアの役割はどうなるのか？」&lt;br/&gt;
        答えは明確です。&lt;strong&gt;「人間は、より高次元な意思決定・設計判断・セキュリティレビューに専念する」&lt;/strong&gt;のです。
    &lt;/p&gt;

    &lt;!-- 図解④ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1PiEDJykZD11mheZw9I2U7sJuQS1IeU10&quot; alt=&quot;人間とAIの役割分担と最終レビュー&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】AIが下準備（90%の定型作業）、人間が意思決定（10%の設計・セキュリティレビュー・マージ承認）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #3b82f6; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #1d4ed8; font-size: 16.5px;&quot;&gt;🔍 AI生成PRに対する「人間の3大レビュー観点」&lt;/strong&gt;
        &lt;ol style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85; color: #1e3a8a;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;業務仕様（ドメインルール）との整合性:&lt;/strong&gt;&lt;br/&gt;
            「そもそも住所が未登録の状態で決済に進めること自体が仕様として正しいのか？ フロントエンドのバリデーション漏れではないか？」といったビジネス文脈の判断は、AIにはできません。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;アーキテクチャ・設計思想の遵守:&lt;/strong&gt;&lt;br/&gt;
            プロジェクトで定めたクリーンアーキテクチャの境界線や命名規則、不要な外部ライブラリへの依存が追加されていないかを厳密にチェックします。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;セキュリティと境界値（エッジケース）:&lt;/strong&gt;&lt;br/&gt;
            SQLインジェクション、機密情報（APIキーや個人情報）の不要なログ出力、悪意のある入力値に対する耐性を人間が最終担保します。&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #fffbeb; border-left: 5px solid #f59e0b; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #b45309; font-size: 16.5px;&quot;&gt;⚠️ 鉄則：AIのPRを「ノータイムマージ」してはならない！&lt;/strong&gt;&lt;br/&gt;
        AIエージェントは非常に優秀ですが、コードの意図を100%理解して責任を取ることはできません。&lt;br/&gt;
        「テストが通っているからOK」と確認なしにマージボタンを押すのは厳禁です。&lt;br/&gt;
        &lt;strong&gt;『AIが完璧な下書きを用意し、人間が責任を持って最終承認する』&lt;/strong&gt;——この健全な役割分担こそが、AI時代の最高峰の開発プラクティスです。
    &lt;/div&gt;

    &lt;!-- まとめセクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;📌 本日の講義まとめと実践チェックリスト&lt;/h2&gt;
    &lt;p&gt;
        Day 26では、AIエージェントとGit/GitHubを融合させた新世代のケーススタディ自動実行（Issue-to-PR）を学びました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 2px solid #e2e8f0; border-radius: 8px; padding: 22px; margin: 25px 0;&quot;&gt;
        &lt;strong style=&quot;color: #1e293b; font-size: 17.5px;&quot;&gt;📋 AIエージェント併用開発チェックリスト&lt;/strong&gt;
        &lt;div style=&quot;margin-top: 14px; line-height: 1.9;&quot;&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ① AIへの指示に「ブランチ作成・修正・テスト・PR起票」の明確なスコープを含めたか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ② AIが &lt;code&gt;dotnet test&lt;/code&gt; を実行し、既存テストを含む全件Greenを確認したか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ③ GitHub PRのタイトルと説明文に変更理由とチケット番号が明記されているか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ④ 人間の目で「仕様の正しさ・設計規約・セキュリティ」の3大観点をレビューしたか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ⑤ レビュー承認（Approve）を経てから安全にマージしたか？&lt;/label&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 20px 24px; margin: 35px 0; border: 1px solid #cbd5e1;&quot;&gt;
        &lt;strong style=&quot;color: #0f172a; font-size: 17px;&quot;&gt;🚀 次回【Day 27】予告&lt;/strong&gt;&lt;br/&gt;
        &lt;div style=&quot;margin-top: 8px; color: #334155; line-height: 1.8;&quot;&gt;
            次回からは&lt;strong&gt;【第6部: プロの調査・保守・作業効率化テクニック】&lt;/strong&gt;が堂々スタート！&lt;br/&gt;
            第1弾のテーマは&lt;strong&gt;【Day 27：git worktree で再ビルドなしの超高速ブランチ並行開発】&lt;/strong&gt;です！&lt;br/&gt;
            巨大なC#ソリューションでブランチを切り替えるたびに発生する「Visual Studioの再ビルド待ち」や「NuGetパッケージ復元待ち」を完全にゼロにする、Gitの神機能 &lt;code&gt;git worktree&lt;/code&gt; を徹底解説します！&lt;br/&gt;
            複数画面で本番調査と機能開発をストレスなく同時進行するプロの秘技を、どうぞお楽しみに！
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/4150710332640774145/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-26case-6ai.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4150710332640774145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4150710332640774145'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-26case-6ai.html' title='【Day 26】【Case 6】AIエージェントを活用したケーススタディ自動実行'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1h6tMOqi7YGXXXTsdsGkK7IBu070nT1s5=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-2704147124030031610</id><published>2026-10-24T09:20:36.470+09:00</published><updated>2026-10-24T09:20:36.470+09:00</updated><title type='text'>【Day 28】ボリューム（Named Volume）によるSQL Serverデータの安全な永続化 〜Docker管理領域によるmdf/ldfファイルの完全保護、docker-compose.ymlでのボリューム定義構文、一時コンテナを用いた安全バックアップ・リストア術、C# EF Core現場でのデータ保持〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1EMZ5I3B9mXaObfbDITD6p3knkqVNkGL9&quot; alt=&quot;Day 28 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 28: ボリューム（Named Volume）によるSQL Serverデータの安全な永続化&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 導入メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: linear-gradient(135deg, #e0f2fe 0%, #f0fdf4 100%); border-left: 6px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0; box-shadow: 0 4px 12px rgba(13,183,237,0.08);&quot;&gt;
        &lt;div style=&quot;font-size: 32px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;font-size: 15.5px; color: #0f172a;&quot;&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; font-weight: bold; color: #0369a1; font-size: 17px;&quot;&gt;「物理サーバーのDドライブのように、SQL ServerのDBレコードを安全に守り抜くにはどうすればいいのか？」&lt;/p&gt;
            &lt;p style=&quot;margin: 0; line-height: 1.8;&quot;&gt;
                前回のDay 27では、Dockerコンテナが「いつでも使い捨てて作り直せるステートレスなプロセス」であり、何も設定せずにデータを書き込むとコンテナ破棄（&lt;code&gt;docker compose down&lt;/code&gt;）と同時にデータが消滅する原理を学びました。&lt;br/&gt;
                では、業務システムの要である &lt;strong&gt;SQL Server のデータベース（.mdf / .ldf）&lt;/strong&gt; は、具体的にどのように保護すべきなのでしょうか？&lt;br/&gt;
                その答えが、Dockerが推奨する &lt;strong&gt;「名前付きボリューム（Named Volume）」&lt;/strong&gt; です！&lt;br/&gt;
                本講義では、SQL Server公式Linuxコンテナのデータ格納構造（&lt;code&gt;/var/opt/mssql/data&lt;/code&gt;）を解剖し、&lt;code&gt;docker-compose.yml&lt;/code&gt; での正しいボリューム宣言、一時コンテナを用いた安全バックアップ＆リストア手法、そしてC# / Entity Framework Core開発における超快適なデータ保護サイクルを徹底解説します！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 目次セクション --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 12px; font-size: 17px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 4px; padding: 2px 8px; font-size: 13px; margin-right: 10px;&quot;&gt;INDEX&lt;/span&gt;
            本日の講義カリキュラム
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #475569; font-size: 15px; line-height: 2;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;第1章: 名前付きボリューム（Named Volume）の基本と仕組み 〜ホスト管理領域の完全隔離〜&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第2章: SQL Server Linuxコンテナのデータ格納構造（/var/opt/mssql/data の秘密）&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第3章: docker-compose.yml での volumes 定義構文 〜2層構造の完全理解〜&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第4章: 実践！Docker CLIによるボリューム管理（create, ls, inspect, prune）&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第5章: 現場必須！一時コンテナ（alpine）を使った安全なデータバックアップ＆リストア手順&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第6章: C# / ASP.NET Core &amp; EF Core 現場での実践運用パターン&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第7章: 本日のまとめと理解度チェッククイズ（次回予告：Day 29 ホットリロード）&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第1章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第1章: 名前付きボリューム（Named Volume）の基本と仕組み 〜ホスト管理領域の完全隔離〜&lt;/h2&gt;

    &lt;p&gt;
        従来のWindows ServerやHyper-V仮想マシンでは、OSドライブ（Cドライブ）とは別に &lt;strong&gt;データ専用の独立ドライブ（DドライブやSAN/NASボリューム）&lt;/strong&gt; を用意し、SQL Serverのデータファイルを配置するのが鉄則でした。OSが故障したり再インストールが必要になったりしても、Dドライブさえデタッチして無事なら、いつでも新しいマシンにアタッチして復旧できたからです。
    &lt;/p&gt;
    &lt;p&gt;
        Dockerにおける &lt;strong&gt;「名前付きボリューム（Named Volume）」&lt;/strong&gt; は、まさにこの &lt;strong&gt;「独立した安全なデータドライブ」&lt;/strong&gt; に相当する機能です。
    &lt;/p&gt;

    &lt;!-- コールアウト: Named Volumeのメリット --&gt;
    &lt;div style=&quot;background: #f1f5f9; border-left: 4px solid #0db7ed; padding: 16px 20px; border-radius: 6px; margin: 20px 0;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 16px;&quot;&gt;💡 なぜバインドマウントではなく「Named Volume」を使うのか？&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.8;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;① ホストOSのファイル権限（UID/GID）の競合ゼロ:&lt;/strong&gt; SQL ServerコンテナはLinux内部で特殊な &lt;code&gt;mssql&lt;/code&gt; ユーザー（UID 10001）で動作します。ホストPCのWindowsフォルダを直接直結（バインドマウント）するとNTFSのパーミッションエラーで起動失敗することが多発しますが、Named VolumeならDocker Engineが内部で安全な権限管理を自動代行します。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;② 高速なI/O性能:&lt;/strong&gt; Windows上でWSL2を使う場合、WindowsのNTFSドライブ（&lt;code&gt;/mnt/c/...&lt;/code&gt;）をマウントするとファイルアクセスが著しく低下します。Named VolumeはWSL2のExt4仮想ディスク内に直接確保されるため、ネイティブLinux並みの圧倒的なディスクI/O速度を誇ります。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;③ 名前によるポータビリティ:&lt;/strong&gt; &lt;code&gt;C:\Users\yamada\data&lt;/code&gt; のような環境依存の絶対パスを書く必要がなく、&lt;code&gt;sqlserver_data&lt;/code&gt; という名前だけで全開発者・CI環境で共通運用できます。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        Named Volumeの実体は、Docker Engineが管理するホスト上の専用領域（Linuxでは &lt;code&gt;/var/lib/docker/volumes/&amp;lt;volume_name&amp;gt;/_data&lt;/code&gt;）に配置されます。コンテナが何百回起動・停止・破棄されようとも、このホスト管理領域の実体ファイルには指一本触れられません。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_28_02_named_volume_concept.png&quot; alt=&quot;Named Volumeの仕組み&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】Dockerホスト管理領域とSQL Serverコンテナ内部（/var/opt/mssql/data）のマウント結合関係&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 第2章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第2章: SQL Server Linuxコンテナのデータ格納構造（/var/opt/mssql/data の秘密）&lt;/h2&gt;

    &lt;p&gt;
        Microsoft公式のSQL Server Linuxコンテナ（&lt;code&gt;mcr.microsoft.com/mssql/server&lt;/code&gt;）を扱う際、エンジニアが必ず押さえておくべき絶対的なパスがあります。それが &lt;strong&gt;&lt;code&gt;/var/opt/mssql/data&lt;/code&gt;&lt;/strong&gt; です。
    &lt;/p&gt;
    &lt;p&gt;
        このディレクトリの中には、SQL Serverのエンジンが稼働するために不可欠なシステムデータベースおよびユーザーデータベースの実体ファイルが全て配置されます：
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 18px 22px; margin: 20px 0; font-family: Consolas, monospace; font-size: 14.5px; overflow-x: auto;&quot;&gt;
# コンテナ内の /var/opt/mssql/data の構成一覧&lt;br/&gt;
/var/opt/mssql/data/&lt;br/&gt;
├── master.mdf          # システム構成・ログイン情報&lt;br/&gt;
├── mastlog.ldf         # masterのトランザクションログ&lt;br/&gt;
├── model.mdf           # 新規DB作成時のテンプレート&lt;br/&gt;
├── modellog.ldf        # modelのトランザクションログ&lt;br/&gt;
├── msdbdata.mdf        # ジョブやバックアップ履歴&lt;br/&gt;
├── msdblog.ldf         # msdbのトランザクションログ&lt;br/&gt;
├── tempdb.mdf          # 一時テーブル（起動毎に再生成）&lt;br/&gt;
├── templog.ldf         # tempdbのトランザクションログ&lt;br/&gt;
├── MyCsharpAppDb.mdf   # ★自作C#アプリのテーブル・データレコード実体&lt;br/&gt;
└── MyCsharpAppDb_log.ldf # ★自作C#アプリのトランザクションログ&lt;br/&gt;
    &lt;/div&gt;

    &lt;p&gt;
        つまり、コンテナ内の &lt;strong&gt;&lt;code&gt;/var/opt/mssql/data&lt;/code&gt; ディレクトリをDockerのNamed Volumeにマウント&lt;/strong&gt; してしまえば、SQL Serverが管理するすべてのデータファイル（&lt;code&gt;.mdf&lt;/code&gt; / &lt;code&gt;.ldf&lt;/code&gt;）がホスト側の安全なボリュームへ自動的に逃がされることになります！
    &lt;/p&gt;

    &lt;!-- 第3章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第3章: docker-compose.yml での volumes 定義構文 〜2層構造の完全理解〜&lt;/h2&gt;

    &lt;p&gt;
        ComposeファイルでNamed Volumeを利用する場合、初心者が最も躓きやすいのが &lt;strong&gt;「2箇所に書く必要がある」&lt;/strong&gt; という点です。
        以下の完成版 &lt;code&gt;docker-compose.yml&lt;/code&gt; をご覧ください。
    &lt;/p&gt;

    &lt;div style=&quot;background: #1e1e1e; color: #d4d4d4; border-radius: 8px; padding: 20px; margin: 20px 0; font-family: Consolas, monospace; font-size: 14px; overflow-x: auto; box-shadow: 0 4px 10px rgba(0,0,0,0.15);&quot;&gt;
&lt;span style=&quot;color: #6a9955;&quot;&gt;# docker-compose.yml: SQL Server Named Volume実践定義&lt;/span&gt;&lt;br/&gt;
&lt;span style=&quot;color: #569cd6;&quot;&gt;services&lt;/span&gt;:&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;db&lt;/span&gt;:&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;image&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;mcr.microsoft.com/mssql/server:2022-latest&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;container_name&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;sqlserver_container&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;environment&lt;/span&gt;:&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #ce9178;&quot;&gt;ACCEPT_EULA=Y&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #ce9178;&quot;&gt;MSSQL_SA_PASSWORD=YourStrong@Passw0rd&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;ports&lt;/span&gt;:&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;1433:1433&quot;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;volumes&lt;/span&gt;:&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# 【階層①】サービス内マウント: &amp;lt;ボリューム名&amp;gt;:&amp;lt;コンテナ内パス&amp;gt;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #ce9178;&quot;&gt;sqlserver_data:/var/opt/mssql/data&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style=&quot;color: #6a9955;&quot;&gt;# 【階層②】トップレベル宣言: プロジェクト全体で利用するNamed Volumeを宣言&lt;/span&gt;&lt;br/&gt;
&lt;span style=&quot;color: #569cd6;&quot;&gt;volumes&lt;/span&gt;:&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;sqlserver_data&lt;/span&gt;:&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;name&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;myproject_sql_volume&lt;/span&gt; &lt;span style=&quot;color: #6a9955;&quot;&gt;# 任意のグローバルボリューム名を明示（省略可能）&lt;/span&gt;&lt;br/&gt;
    &lt;/div&gt;

    &lt;p&gt;
        この2層構造の役割を明確に区別しましょう：
    &lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;① サービス内 volumes:&lt;/strong&gt; 個々のコンテナに対して「どのボリュームを」「コンテナ内のどこに差し込む（マウントする）か」を指示する &lt;strong&gt;プラグの接続設定&lt;/strong&gt; です。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;② トップレベル volumes:&lt;/strong&gt; Docker Engineに対して「この名前の永続化ボリューム実体を1個確保せよ」と命じる &lt;strong&gt;金庫自体の作成宣言&lt;/strong&gt; です。ここに書かないと、Composeは「そんなボリューム定義は存在しない」とエラーを出します。&lt;/li&gt;
    &lt;/ul&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_28_03_compose_volume_syntax.png&quot; alt=&quot;Composeでのボリューム定義&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】docker-compose.ymlにおけるサービス内マウントとトップレベルvolumes宣言の2層構造&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 第4章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第4章: 実践！Docker CLIによるボリューム管理（create, ls, inspect, prune）&lt;/h2&gt;

    &lt;p&gt;
        普段は &lt;code&gt;docker compose up&lt;/code&gt; で自動生成されるNamed Volumeですが、障害対応やディスクメンテナンス時にはDocker CLIから直接操作できることが現場エンジニアの必須スキルです。
    &lt;/p&gt;

    &lt;!-- CLIテーブル --&gt;
    &lt;div style=&quot;overflow-x: auto; margin: 24px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 14.5px; text-align: left;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #0f172a; color: #ffffff;&quot;&gt;
                    &lt;th style=&quot;padding: 12px 14px; border: 1px solid #334155;&quot;&gt;コマンド&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 14px; border: 1px solid #334155;&quot;&gt;機能説明&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 14px; border: 1px solid #334155;&quot;&gt;実務でのユースケース&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-family: monospace; font-weight: bold; color: #0369a1;&quot;&gt;docker volume ls&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;存在するボリュームの一覧表示&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;現在PCに溜まっているDBボリュームの確認&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-family: monospace; font-weight: bold; color: #0369a1;&quot;&gt;docker volume inspect &amp;lt;名&amp;gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;ボリュームの詳細情報（Mountpoint）表示&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;ホストOS上の物理保存先パスの特定&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-family: monospace; font-weight: bold; color: #0369a1;&quot;&gt;docker volume create &amp;lt;名&amp;gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;名前を指定して手動作成&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;事前に共通データボリュームを仕込んでおく場合&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-family: monospace; font-weight: bold; color: #e11d48;&quot;&gt;docker volume rm &amp;lt;名&amp;gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;特定ボリュームの削除&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;テスト環境を完全破棄したい時（※コンテナ停止要）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-family: monospace; font-weight: bold; color: #e11d48;&quot;&gt;docker volume prune&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;どのコンテナにも繋がっていないボリューム一括削除&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;SSD空き容量の劇的回復（※未接続ボリューム消滅注意）&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- 警告コールアウト --&gt;
    &lt;div style=&quot;background: #fff1f2; border-left: 4px solid #e11d48; padding: 16px 20px; border-radius: 6px; margin: 20px 0;&quot;&gt;
        &lt;strong style=&quot;color: #9f1239; font-size: 16px;&quot;&gt;⚠️ 現場で最も恐ろしい「down -v」の誤爆事故&lt;/strong&gt;
        &lt;p style=&quot;margin: 6px 0 0 0; color: #881337; line-height: 1.8;&quot;&gt;
            普段の &lt;code&gt;docker compose down&lt;/code&gt; では、コンテナプロセスのみが破棄され、Named Volumeは無傷で残ります。&lt;br/&gt;
            しかし、末尾に &lt;code&gt;-v&lt;/code&gt;（または &lt;code&gt;--volumes&lt;/code&gt;）を付与して &lt;code&gt;docker compose down -v&lt;/code&gt; と叩くと、&lt;strong&gt;トップレベルで宣言されたNamed Volumeごと物理削除&lt;/strong&gt; されます！テストレコードを意図してリセットしたい場合を除き、日常の停止時には絶対に &lt;code&gt;-v&lt;/code&gt; を付けないよう指差呼称してください。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 第5章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第5章: 現場必須！一時コンテナ（alpine）を使った安全なデータバックアップ＆リストア手順&lt;/h2&gt;

    &lt;p&gt;
        「Named Volumeの中身をバックアップして別のPCに持っていきたい」「本番に近いテストデータを開発チーム全員に配布したい」というシチュエーションは現場で日常茶飯事です。&lt;br/&gt;
        しかし、Named Volumeの実体フォルダ（&lt;code&gt;/var/lib/docker/volumes/...&lt;/code&gt;）はroot権限で保護されており、Windowsエクスプローラーから直接ZIP圧縮することは困難です。
    &lt;/p&gt;
    &lt;p&gt;
        そこで、Dockerの世界で標準的に使われるプロの手法が &lt;strong&gt;「超軽量な一時コンテナ（alpine）を用いたtarアーカイブバックアップ」&lt;/strong&gt; です！
    &lt;/p&gt;

    &lt;!-- 3ステップコード --&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 20px; margin: 20px 0; font-family: Consolas, monospace; font-size: 14px; overflow-x: auto;&quot;&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;# 【手順1: バックアップ】Named Volumeを一時コンテナにマウントし、ホスト側へtar.gz出力&lt;/span&gt;&lt;br/&gt;
docker run --rm \&lt;br/&gt;
&amp;nbsp;&amp;nbsp;-v sqlserver_data:/dbdata \&lt;br/&gt;
&amp;nbsp;&amp;nbsp;-v ${PWD}:/backup \&lt;br/&gt;
&amp;nbsp;&amp;nbsp;alpine tar czvf /backup/sqlserver_backup.tar.gz -C /dbdata .&lt;br/&gt;
&lt;br/&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;# 【手順2: リストア（復元）】新規作成したボリュームにtar.gzを展開&lt;/span&gt;&lt;br/&gt;
docker run --rm \&lt;br/&gt;
&amp;nbsp;&amp;nbsp;-v sqlserver_data:/dbdata \&lt;br/&gt;
&amp;nbsp;&amp;nbsp;-v ${PWD}:/backup \&lt;br/&gt;
&amp;nbsp;&amp;nbsp;alpine tar xzvf /backup/sqlserver_backup.tar.gz -C /dbdata&lt;br/&gt;
    &lt;/div&gt;

    &lt;p&gt;
        このワンライナーがなぜエレガントなのか、その仕組みを紐解きましょう：
    &lt;/p&gt;
    &lt;ol&gt;
        &lt;li&gt;&lt;code&gt;--rm&lt;/code&gt; オプションにより、tar圧縮・展開の処理が終わった瞬間に一時コンテナ（alpine）は自動で消滅します（ゴミが残りません）。&lt;/li&gt;
        &lt;li&gt;Named Volume（&lt;code&gt;sqlserver_data&lt;/code&gt;）を &lt;code&gt;/dbdata&lt;/code&gt; に、ホスト側のカレントディレクトリ（&lt;code&gt;${PWD}&lt;/code&gt;）を &lt;code&gt;/backup&lt;/code&gt; に同時にマウントします。&lt;/li&gt;
        &lt;li&gt;コンテナ内部で &lt;code&gt;tar&lt;/code&gt; コマンドが走り、&lt;code&gt;/dbdata&lt;/code&gt; の中身（.mdf/.ldfファイル群）を瞬時に圧縮して、ホスト側の &lt;code&gt;/backup/sqlserver_backup.tar.gz&lt;/code&gt; に保存してくれます。&lt;/li&gt;
    &lt;/ol&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_28_04_backup_restore_flow.png&quot; alt=&quot;ボリュームのバックアップ手順&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】一時コンテナ（alpine）を活用したNamed Volumeのtarアーカイブ安全バックアップ・リストア 3ステップ&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 第6章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第6章: C# / ASP.NET Core &amp; EF Core 現場での実践運用パターン&lt;/h2&gt;

    &lt;p&gt;
        Named Volumeを導入することで、C#エンジニアの開発体験（Developer Experience）は劇的に進化します。
    &lt;/p&gt;

    &lt;!-- C#とEF Coreの接続文字列 --&gt;
    &lt;h3 style=&quot;color: #0f172a; font-size: 18px; margin-top: 25px;&quot;&gt;① EF Core マイグレーションとボリュームの共存&lt;/h3&gt;
    &lt;p&gt;
        ASP.NET Coreアプリケーション起動時に &lt;code&gt;DbContext.Database.Migrate()&lt;/code&gt; を呼び出す設計を採用している場合、初回起動時にテーブルが自動作成され、テストシードデータが投入されます。&lt;br/&gt;
        もしボリュームがなければ、C#コードを修正してコンテナを再起動するたびに「初期化スクリプト」が最初から走り直し、手動で画面からポチポチ登録したテストユーザーや受注レコードが吹き飛んでいました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #1e1e1e; color: #d4d4d4; border-radius: 8px; padding: 20px; margin: 20px 0; font-family: Consolas, monospace; font-size: 14px; overflow-x: auto;&quot;&gt;
&lt;span style=&quot;color: #6a9955;&quot;&gt;// Program.cs: アプリ起動時の自動マイグレーション例&lt;/span&gt;&lt;br/&gt;
&lt;span style=&quot;color: #569cd6;&quot;&gt;using&lt;/span&gt; (&lt;span style=&quot;color: #569cd6;&quot;&gt;var&lt;/span&gt; scope = app.Services.CreateScope())&lt;br/&gt;
{&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #569cd6;&quot;&gt;var&lt;/span&gt; dbContext = scope.ServiceProvider.GetRequiredService&amp;lt;AppDbContext&amp;gt;();&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;// Named VolumeにDBファイルが存在すればマイグレーション履歴テーブル(__EFMigrationsHistory)&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;// を見て差分のみ適用されるため、既存データは完全に安全！&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dbContext.Database.Migrate();&lt;br/&gt;
}&lt;br/&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; font-size: 18px; margin-top: 25px;&quot;&gt;② チーム開発におけるGitとボリュームの運用ルール&lt;/h3&gt;
    &lt;p&gt;
        チームでDockerを活用する際の鉄則は、&lt;strong&gt;「Gitで共有するのはコードとマイグレーション（.csファイル）だけであり、Named VolumeのDB実体ファイル（.mdf/.ldf）は絶対にGitにコミットしない」&lt;/strong&gt; ということです。
    &lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;Gitの役割:&lt;/strong&gt; データベースの「スキーマ定義（設計図）」を全員で同期する。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Volumeの役割:&lt;/strong&gt; 各開発者のPC上で動作する「生データ（テストレコード）」をローカルで安全に保持する。&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;
        これにより、Gitのブランチを切り替えて新機能を実装し、コンテナを &lt;code&gt;docker compose up -d --build&lt;/code&gt; で差分再ビルドしても、昨日登録したログインセッションや複雑なテストデータがそのまま保持されるため、開発効率が何十倍にも向上します！
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;C:\011_開発\Docker講座\images\day_28_05_csharp_db_persistence.png&quot; alt=&quot;C#現場の開発ワークフロー&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】C#開発現場におけるデータ保護恩恵（コード更新・再ビルド時もテストDBレコードを完全保持）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 第7章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第7章: 本日のまとめと理解度チェッククイズ&lt;/h2&gt;

    &lt;!-- まとめボックス --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0369a1; margin-top: 0; font-size: 18px;&quot;&gt;📌 本日の最重要チェックポイント&lt;/h3&gt;
        &lt;ol style=&quot;margin: 0; padding-left: 22px; line-height: 2; color: #334155; font-size: 15.5px;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;Named VolumeはDocker管理の安全な独立データドライブ:&lt;/strong&gt; ホストOSの権限競合を防ぎ、最高速のディスクI/Oを提供。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;SQL Serverの格納先は &lt;code&gt;/var/opt/mssql/data&lt;/code&gt;:&lt;/strong&gt; ここをボリュームにマウントすることで、すべてのmdf/ldfファイルがコンテナ外へ保護される。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Compose定義は「サービス内」と「トップレベル」の2層構造:&lt;/strong&gt; サービス内でマウント先を指定し、最下部で実体宣言を行う。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;日常は &lt;code&gt;down&lt;/code&gt;、リセット時のみ &lt;code&gt;down -v&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;-v&lt;/code&gt; オプションを誤爆するとボリュームごとデータ消滅するため厳格注意。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;バックアップは一時コンテナ（alpine）のtarが業界標準:&lt;/strong&gt; コンテナを汚染せず、ホスト側へクリーンにtar.gzアーカイブを出力可能。&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;!-- 理解度チェッククイズ --&gt;
    &lt;div style=&quot;background: #ffffff; border: 1px solid #cbd5e1; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; font-size: 17px;&quot;&gt;🎯 理解度チェッククイズ&lt;/h3&gt;
        &lt;p style=&quot;margin: 0 0 10px 0; color: #475569; font-weight: bold;&quot;&gt;Q: docker-compose.ymlでNamed Volumeを利用してSQL Serverを起動している現場で、開発者が叩いたコマンドのうち、データベースのデータが「完全に消滅してしまう」ものはどれでしょうか？&lt;/p&gt;
        &lt;ul style=&quot;margin: 0 0 15px 0; padding-left: 20px; color: #334155; line-height: 1.8;&quot;&gt;
            &lt;li&gt;A. &lt;code&gt;docker compose stop&lt;/code&gt;&lt;/li&gt;
            &lt;li&gt;B. &lt;code&gt;docker compose down&lt;/code&gt;&lt;/li&gt;
            &lt;li&gt;C. &lt;code&gt;docker compose up -d --build&lt;/code&gt;&lt;/li&gt;
            &lt;li&gt;D. &lt;code&gt;docker compose down -v&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
        &lt;details style=&quot;background: #f1f5f9; padding: 12px 16px; border-radius: 6px; cursor: pointer;&quot;&gt;
            &lt;summary style=&quot;font-weight: bold; color: #0284c7;&quot;&gt;正解と解説を見る&lt;/summary&gt;
            &lt;p style=&quot;margin: 10px 0 0 0; color: #0f172a; line-height: 1.8;&quot;&gt;
                &lt;strong&gt;正解: D. &lt;code&gt;docker compose down -v&lt;/code&gt;&lt;/strong&gt;&lt;br/&gt;
                通常の &lt;code&gt;stop&lt;/code&gt; や &lt;code&gt;down&lt;/code&gt;、再ビルドを伴う &lt;code&gt;up -d --build&lt;/code&gt; では、Named Volumeは完全に維持されるためDBデータは消えません。しかし、&lt;code&gt;-v&lt;/code&gt;（または &lt;code&gt;--volumes&lt;/code&gt;）フラグを付けて実行すると、コンテナだけでなく定義されたボリューム自体が破棄されるため、データが完全に初期化されます。意図的なデータリセット以外では絶対に付与しないようにしましょう。
            &lt;/p&gt;
        &lt;/details&gt;
    &lt;/div&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background: linear-gradient(135deg, #fdf4ff 0%, #fae8ff 100%); border-left: 6px solid #c026d3; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #86198f; margin-top: 0; font-size: 17px;&quot;&gt;🚀 次回予告（Day 29）&lt;/h3&gt;
        &lt;p style=&quot;margin: 0; color: #701a75; line-height: 1.8;&quot;&gt;
            次回は永続化のもう一つの主役、&lt;strong&gt;「バインドマウント（Bind Mount）によるソースコード即時反映（ホットリロード）」&lt;/strong&gt; を徹底攻略します！&lt;br/&gt;
            C#コードを保存した瞬間にコンテナ内で自動再起動・即時反映される &lt;code&gt;dotnet watch&lt;/code&gt; とバインドマウントの超高速開発サイクルを構築します。お楽しみに！
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/2704147124030031610/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-28named-volumesql-server.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/2704147124030031610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/2704147124030031610'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-28named-volumesql-server.html' title='【Day 28】ボリューム（Named Volume）によるSQL Serverデータの安全な永続化 〜Docker管理領域によるmdf/ldfファイルの完全保護、docker-compose.ymlでのボリューム定義構文、一時コンテナを用いた安全バックアップ・リストア術、C# EF Core現場でのデータ保持〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1EMZ5I3B9mXaObfbDITD6p3knkqVNkGL9=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-1791111503627724423</id><published>2026-10-23T18:10:44.845+09:00</published><updated>2026-10-23T18:10:44.845+09:00</updated><title type='text'>【Day 25】【Case 5】仕様変更・機能のリリース順序入れ替え（チェリーピック）</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/14hpFOtuGHHYz6ZxLAhxekYBaQILIeXod&quot; alt=&quot;Day 25 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 25】仕様変更・機能のリリース順序入れ替え（チェリーピック）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 24では、本番環境の緊急障害に対応する「Hotfix」の完全手順と、developへのマージバックによる先祖返り防止サイクルを学びました。&lt;br/&gt;
            本日のDay 25は、現場のエンジニアなら誰しも一度は遭遇する波乱のシチュエーション——&lt;strong&gt;【仕様変更・機能のリリース順序入れ替え（チェリーピック）】&lt;/strong&gt;を徹底解説します！&lt;br/&gt;
            「次の定期リリースに向けて、機能A（AIレコメンド機能）と機能B（請求書PDF決済機能）を並行して開発していたが、突然クライアントや経営陣から『機能Aは仕様再検討で来月に延期！でも機能Bだけは契約上、明日のリリースにどうしても間に合わせてほしい！』と頼まれた……」&lt;br/&gt;
            このような「リリース順序の逆転」や「特定機能だけの先行リリース」は、アジャイル開発でも受託開発でも日常茶飯事です。&lt;br/&gt;
            Subversion (SVN) や Visual SourceSafe (VSS) で開発していた時代、これに対応するのはまさに悪夢でした。トランク（trunk）に時系列でコミットされた変更の中から、関係するファイル差分を手作業で洗い出し、別ブランチへ手動でコピペしてビルドする「手動リビジョンマージ」を行っていました。その結果、未完成な機能Aのコードが誤って混入したり、コピペ漏れによるコンパイルエラーや実行時例外が多発していました。&lt;br/&gt;
            しかしGitなら、&lt;strong&gt;「git cherry-pick」&lt;/strong&gt;という極めて強力な武器があります！&lt;br/&gt;
            Gitのコミットは、独立した変更パッチとして管理されています。そのため、木になっている熟した美味しいさくらんぼをスプーンで摘まみ取るように、&lt;strong&gt;「機能Bに関する特定のコミットだけ」&lt;/strong&gt;を狙い撃ちして、安全にリリースブランチや本番ブランチへ移植・複製することができます！&lt;br/&gt;
            本日は、Git CLIおよびTortoiseGitを使ったチェリーピックの完全手順、C#プロジェクトにおけるサービスクラス抽出の実戦例、&lt;code&gt;dotnet test&lt;/code&gt;による二次災害防止、そしてコンフリクト発生時の対処（&lt;code&gt;--continue&lt;/code&gt; / &lt;code&gt;--abort&lt;/code&gt;）まで、現場で即戦力となるプロフェッショナルの技術を余すところなくお伝えします！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        アジャイルやスプリント開発の現場では、ビジネス環境の変化や顧客からの要望によって、開発ロードマップが急遽変更されることが頻繁にあります。&lt;br/&gt;
        「ブランチ全体を丸ごとマージすることはできないが、特定の機能コミットだけを今すぐ本番へ届けたい」。&lt;br/&gt;
        この要求にスマートに応えられるかどうかが、一人前のGitエンジニアとしての腕の見せ所です。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;SVNの「差分手動適用の混乱・ファイル混在事故」とGitの「コミット単位の安全な摘み食い（チェリーピック）」の違いを理解する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git log&lt;/code&gt; で目的のハッシュを特定し、&lt;code&gt;git cherry-pick&lt;/code&gt; で特定コミットを別ブランチへ安全に移植する3ステップを習得する&lt;/li&gt;
            &lt;li&gt;C#プロジェクトにおいて、未完成クラス（AI機能）を延期しつつ完成クラス（決済サービス）のコミットだけを抽出し、&lt;code&gt;dotnet test&lt;/code&gt; で検証する実戦手順を身につける&lt;/li&gt;
            &lt;li&gt;TortoiseGitのコミットログ画面から、マウス操作で視覚的にチェリーピックを実行する手順を理解する&lt;/li&gt;
            &lt;li&gt;コンフリクト（競合）発生時の解消作法（&lt;code&gt;--continue&lt;/code&gt; と &lt;code&gt;--abort&lt;/code&gt;）およびコミットハッシュが変わる仕組みを把握する&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: SVN vs Git cherry-pick --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】SVNのリビジョンマージ vs Gitのチェリーピック：なぜGitなら安全に「摘み食い」できるのか？&lt;/h2&gt;
    &lt;p&gt;
        まず、従来のSVNにおける部分マージと、Gitのチェリーピックの構造的な違いを比較してみましょう。
    &lt;/p&gt;

    &lt;!-- 図解① --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1V8Q3J8KMstWm64ak4aF1O95sukEgNDl2&quot; alt=&quot;SVNリビジョンマージ vs Gitチェリーピック&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】SVNの「差分手動適用の混乱（ファイル混在事故）」vs Gitの「コミット単位の綺麗な摘み食い（チェリーピック）」&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        集中型バージョン管理（SVN）では、中央リポジトリの &lt;code&gt;trunk&lt;/code&gt; にすべてのコミットが直線的に並んでいました。&lt;br/&gt;
        特定の修正だけを別ブランチ（リリース用ブランチなど）に反映したい場合、SVNの &lt;code&gt;svn merge -c [リビジョン番号]&lt;/code&gt; を実行するか、変更されたソースファイルを手動で特定して別フォルダにコピペする手法が取られていました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #fff1f2; border-left: 5px solid #e11d48; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #be123c; font-size: 16.5px;&quot;&gt;💥 SVN時代のリビジョンマージで頻発した事故&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85; color: #4c0519;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;不要な差分の巻き込み:&lt;/strong&gt; 1つのリビジョンに複数の変更が混在していたり、依存関係が曖昧なため、リリースしてはいけない未完成コードや実験的設定が誤って紛れ込む。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;追跡不能なマージ履歴:&lt;/strong&gt; どのリビジョンがどこへマージされたのか履歴グラフとして視覚化されず、後から「このコードはいつ誰が移植したのか？」が闇に葬られる。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;手動コピペによるヒューマンエラー:&lt;/strong&gt; 開発者が慌ててファイルを手動で上書きした結果、別の修正が先祖返りで吹き飛ぶ。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        これに対し、Gitにおけるコミットは&lt;strong&gt;「親コミットからの完全な差分スナップショット」&lt;/strong&gt;です。&lt;br/&gt;
        Gitの &lt;code&gt;cherry-pick&lt;/code&gt; は、指定したコミットの差分内容を自動的にパッチとして抽出し、現在チェックアウトしているブランチの先端に&lt;strong&gt;「まったく新しいコミット」&lt;/strong&gt;として適用してくれます。&lt;br/&gt;
        これにより、他のブランチの未完成なコードには一切影響を与えず、必要な機能コミットだけをクリーンかつ確実に抜き出すことができるのです。
    &lt;/p&gt;

    &lt;!-- セクション③: チェリーピックの基本手順 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】チェリーピックの仕組みと実行の3ステップ完全手順&lt;/h2&gt;
    &lt;p&gt;
        Git CLIを用いたチェリーピックの基本操作は、極めてシンプルです。
    &lt;/p&gt;

    &lt;!-- 図解② --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1rCi_AVCiS1ReQZ0l4tCQqTnJF0ahofve&quot; alt=&quot;チェリーピックの仕組みと実行の3ステップ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】ハッシュ確認・ブランチ切り替え・cherry-pick実行の3ステップと新コミット生成の仕組み&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;ステップ1: 移植したいコミットのハッシュ値を確認する&lt;/h3&gt;
    &lt;p&gt;
        まず、抜き出したいコミットが存在するブランチのログを確認し、コミットハッシュ（7桁程度の英数字）を控えます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# コミット履歴を1行形式で確認&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; log --oneline develop&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 出力例:&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;c7d8e9f&lt;/span&gt; feat(ai): AIレコメンドエンジンの初期実装 (※今回は延期)&lt;br/&gt;
        &lt;span style=&quot;color: #4ade80; font-weight: bold;&quot;&gt;b2c3d4e&lt;/span&gt; &lt;span style=&quot;color: #4ade80;&quot;&gt;feat(invoice): 請求書PDF決済サービスの追加 (★これを先行リリースしたい！)&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;a1b2c3d&lt;/span&gt; docs: 仕様書ドキュメント更新
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;ステップ2: 移植先のブランチへ切り替える&lt;/h3&gt;
    &lt;p&gt;
        コミットを受け取りたいブランチ（例: &lt;code&gt;release/1.1&lt;/code&gt; や &lt;code&gt;main&lt;/code&gt;）へスイッチします。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# リリースブランチへ切り替え&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch release/1.1
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;ステップ3: git cherry-pick を実行する&lt;/h3&gt;
    &lt;p&gt;
        控えておいたコミットハッシュを指定して、チェリーピックを実行します。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 特定コミットを現在のブランチへ適用&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; cherry-pick b2c3d4e&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 複数コミットを連続適用したい場合（スペース区切り）&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; cherry-pick b2c3d4e f1a2b3c&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 範囲指定で一括適用したい場合 (古いコミット..新しいコミット ※古い側は含まない)&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; cherry-pick a1b2c3d..b2c3d4e
    &lt;/div&gt;

    &lt;div style=&quot;background: #f0fdf4; border-left: 5px solid #22c55e; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #15803d; font-size: 16.5px;&quot;&gt;💡 重要ポイント：コミットハッシュは「新しく」なる！&lt;/strong&gt;&lt;br/&gt;
        チェリーピックで適用されたコミットは、変更内容やコミットメッセージは元と同じですが、&lt;strong&gt;「親コミット（直前のコミット）」が異なるため、新しいハッシュ値（SHA-1）が割り当てられます&lt;/strong&gt;。&lt;br/&gt;
        元のコミットが移動するのではなく、クローン（複製）が移植先ブランチの先端に生成されると理解してください。
    &lt;/div&gt;

    &lt;!-- セクション④: C#現場での実戦例 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【実戦C#編】仕様変更による特定サービスクラスの抽出とdotnet test検証&lt;/h2&gt;
    &lt;p&gt;
        実際のC#ソリューションでの具体的なケーススタディを見てみましょう。
    &lt;/p&gt;

    &lt;!-- 図解③ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/129SIoKmpUqrTHSPNjDUZH4iMjDoplvPF&quot; alt=&quot;C#現場での機能抽出とdotnet test検証&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】C#現場での機能分離（未完成AI機能の延期と請求書決済サービスの先行抽出）およびdotnet testによる整合性担保&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        Web APIプロジェクトにおいて、&lt;code&gt;develop&lt;/code&gt; ブランチ上で次のような2つの新機能が追加コミットされていたとします。
    &lt;/p&gt;
    &lt;ol style=&quot;margin: 10px 0; padding-left: 24px; line-height: 1.8;&quot;&gt;
        &lt;li&gt;&lt;code&gt;AiRecommendationService.cs&lt;/code&gt;: OpenAI APIを呼び出すレコメンド機能（※外部API仕様が未確定のためリリース延期決定）&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;InvoicePaymentService.cs&lt;/code&gt;: 請求書決済ロジック（※顧客要請により先行リリース決定）&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 25px; font-size: 18px;&quot;&gt;C#プロジェクトでの抽出手順&lt;/h3&gt;
    &lt;p&gt;
        未完成のAI機能が混ざらないよう、請求書決済機能のコミット（および単体テストのコミット）だけを &lt;code&gt;release/1.1&lt;/code&gt; にチェリーピックします。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# リリースブランチでコミットを摘出&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch release/1.1&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; cherry-pick 8f4a12b&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# C#ソリューションのビルド確認&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;dotnet&lt;/span&gt; build --configuration Release&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 単体テストの実行（回帰テスト＆新機能テスト）&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;dotnet&lt;/span&gt; test --no-build --verbosity normal
    &lt;/div&gt;

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #3b82f6; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #1d4ed8; font-size: 16.5px;&quot;&gt;🛡️ C#エンジニアが絶対に守るべき「DI登録と依存関係」の確認&lt;/strong&gt;&lt;br/&gt;
        C#（ASP.NET Core）では、サービスクラス単体だけでなく &lt;code&gt;Program.cs&lt;/code&gt; でのDI登録（&lt;code&gt;builder.Services.AddScoped&amp;lt;IInvoicePaymentService, InvoicePaymentService&amp;gt;();&lt;/code&gt;）が必要です。&lt;br/&gt;
        コミットを分ける際は、「サービスクラスの実装」と「Program.csへの登録」「単体テスト」が正しく1つの機能コミット（または関連コミット群）にまとまっていることが重要です。&lt;br/&gt;
        もしDI登録のコミットをチェリーピックし忘れると、実行時に &lt;code&gt;InvalidOperationException: Unable to resolve service for type...&lt;/code&gt; が発生するため、チェリーピック直後の &lt;code&gt;dotnet test&lt;/code&gt; 実行は必須の安全弁となります！
    &lt;/div&gt;

    &lt;!-- セクション⑤: TortoiseGitでの視覚的操作 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【GUI操作】TortoiseGitでの右クリックチェリーピックと競合解消&lt;/h2&gt;
    &lt;p&gt;
        Windows / エクスプローラー上で直感的に作業したい開発者のために、TortoiseGitでのチェリーピック手順とコンフリクト対策を確認しましょう。
    &lt;/p&gt;

    &lt;!-- 図解④ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1R4MccZzb-e-Dtu9a97HyFrtB1W2bSleL&quot; alt=&quot;TortoiseGitでの右クリック操作と重要ポイント&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】TortoiseGitでの視覚的チェリーピック操作とコンフリクト時の--continue / --abort対応&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; margin-top: 25px; font-size: 18px;&quot;&gt;TortoiseGitでの操作手順&lt;/h3&gt;
    &lt;ol style=&quot;margin: 10px 0; padding-left: 24px; line-height: 1.85;&quot;&gt;
        &lt;li&gt;エクスプローラーで作業フォルダを右クリックし、移植先ブランチ（&lt;code&gt;release/1.1&lt;/code&gt;）にスイッチします。&lt;/li&gt;
        &lt;li&gt;右クリックメニューから &lt;strong&gt;[TortoiseGit] → [ログを表示 (Show Log)]&lt;/strong&gt; を開きます。&lt;/li&gt;
        &lt;li&gt;画面左上のブランチ選択で「すべて参照 (All Branches)」または &lt;code&gt;develop&lt;/code&gt; を選択し、コミット一覧を表示します。&lt;/li&gt;
        &lt;li&gt;移植したいコミットを右クリックし、&lt;strong&gt;[このコミットをチェリーピック (Cherry Pick this commit...)]&lt;/strong&gt; を選択します。&lt;/li&gt;
        &lt;li&gt;確認ダイアログで [続行 (Continue)] を押すと、瞬時に現在のブランチへ変更が適用されます。&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;万が一コンフリクト（競合）が発生した場合の対処&lt;/h3&gt;
    &lt;p&gt;
        もし移植対象のコードが、移植先ブランチの既存コードと同一箇所を変更していた場合、チェリーピックは一時停止してコンフリクト状態になります。&lt;br/&gt;
        焦る必要はありません。Gitは安全のために停止しているだけです。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 6px; padding: 18px; margin: 15px 0;&quot;&gt;
        &lt;strong style=&quot;color: #334155; font-size: 16px;&quot;&gt;🔧 コンフリクト時の3大コマンド&lt;/strong&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 15px;&quot;&gt;
            &lt;tr style=&quot;background: #f1f5f9; border-bottom: 2px solid #cbd5e1;&quot;&gt;
                &lt;th style=&quot;padding: 10px; text-align: left; width: 35%;&quot;&gt;コマンド&lt;/th&gt;
                &lt;th style=&quot;padding: 10px; text-align: left;&quot;&gt;説明と使い所&lt;/th&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                &lt;td style=&quot;padding: 10px; font-family: Consolas, monospace; color: #0284c7;&quot;&gt;&lt;strong&gt;git cherry-pick --continue&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;競合ファイルをエディタやTortoiseGitマージで解決し、&lt;code&gt;git add&lt;/code&gt; した後に入力してチェリーピックを再開・完了する。&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                &lt;td style=&quot;padding: 10px; font-family: Consolas, monospace; color: #e11d48;&quot;&gt;&lt;strong&gt;git cherry-pick --abort&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;「競合が複雑すぎる！一旦元の状態に戻したい！」という時に実行。チェリーピック開始前の状態に完全ロールバックする。&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;padding: 10px; font-family: Consolas, monospace; color: #d97706;&quot;&gt;&lt;strong&gt;git cherry-pick --skip&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;複数コミットを範囲指定した際、特定のコミットが既に適用済みなどの理由で不要な場合にスキップする。&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑥: 重要注意点とベストプラクティス --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ チェリーピック運用の鉄則と「後からの全体マージ」の挙動&lt;/h2&gt;
    &lt;p&gt;
        「チェリーピックしたコミットは、後から &lt;code&gt;develop&lt;/code&gt; を &lt;code&gt;main&lt;/code&gt; に正式マージしたときに重複してコンフリクトしないのか？」&lt;br/&gt;
        これは多くのエンジニアが抱く疑問です。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f0fdf4; border-left: 5px solid #16a34a; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #15803d; font-size: 16.5px;&quot;&gt;💡 Gitの賢い仕組み：パッチIDによる重複検知&lt;/strong&gt;&lt;br/&gt;
        Gitは内部的に「パッチID（変更内容のハッシュ）」を比較する仕組みを持っています。&lt;br/&gt;
        そのため、後日 &lt;code&gt;develop&lt;/code&gt; ブランチ全体を &lt;code&gt;main&lt;/code&gt; や &lt;code&gt;release&lt;/code&gt; にマージした際、Gitは&lt;strong&gt;「この変更はチェリーピックですでに適用済みである」と自動検知し、重複適用をスキップ&lt;/strong&gt;してくれます！&lt;br/&gt;
        したがって、チェリーピックを行ったからといって将来のマージが破綻することはありません。
    &lt;/div&gt;

    &lt;div style=&quot;background: #fffbeb; border-left: 5px solid #f59e0b; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #b45309; font-size: 16.5px;&quot;&gt;⚠️ ただし乱用は禁物！3つの運用ルール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85; color: #78350f;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;コミットの粒度を小さく保つ:&lt;/strong&gt; 1つのコミットに「AI機能」と「決済機能」が混ざっていると、チェリーピックで分離できません。普段から「1機能1コミット」を徹底しましょう。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;チェリーピックのログを残す:&lt;/strong&gt; &lt;code&gt;git cherry-pick -x [ハッシュ]&lt;/code&gt; とオプション &lt;code&gt;-x&lt;/code&gt; を付けると、コミットメッセージに「(cherry picked from commit ...)」という出処が自動記録され、チームメンバーが追跡しやすくなります。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;迷ったらブランチ全体の再構築を検討:&lt;/strong&gt; 10個も20個もチェリーピックを乱発する事態になったら、抽出ブランチを新設して必要な機能ブランチだけをマージする構成を検討しましょう。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- まとめセクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;📌 本日の講義まとめと実践チェックリスト&lt;/h2&gt;
    &lt;p&gt;
        Day 25では、現場の仕様変更やリリース順序入れ替えに柔軟に対応する「チェリーピック」の真髄を学びました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 2px solid #e2e8f0; border-radius: 8px; padding: 22px; margin: 25px 0;&quot;&gt;
        &lt;strong style=&quot;color: #1e293b; font-size: 17.5px;&quot;&gt;📋 チェリーピック実践チェックリスト&lt;/strong&gt;
        &lt;div style=&quot;margin-top: 14px; line-height: 1.9;&quot;&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ① &lt;code&gt;git log --oneline&lt;/code&gt; で移植したいコミットハッシュを確実に控えたか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ② 適用先ブランチ（release等）に &lt;code&gt;git switch&lt;/code&gt; してから実行したか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ③ C#コードのDI登録漏れや参照エラーがないか &lt;code&gt;dotnet build&lt;/code&gt; で確認したか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ④ 既存機能の破壊やデグレがないか &lt;code&gt;dotnet test&lt;/code&gt; で単体テストを通したか？&lt;/label&gt;
            &lt;label style=&quot;display: block; margin-bottom: 8px;&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; ⑤ コンフリクト発生時は慌てず &lt;code&gt;--continue&lt;/code&gt; または &lt;code&gt;--abort&lt;/code&gt; で適切に対処できたか？&lt;/label&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 次回予告 --&gt;
    &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 20px 24px; margin: 35px 0; border: 1px solid #cbd5e1;&quot;&gt;
        &lt;strong style=&quot;color: #0f172a; font-size: 17px;&quot;&gt;🚀 次回【Day 26】予告&lt;/strong&gt;&lt;br/&gt;
        &lt;div style=&quot;margin-top: 8px; color: #334155; line-height: 1.8;&quot;&gt;
            次回はケーススタディ第6弾！&lt;strong&gt;【【Case 6】AIエージェントを活用したケーススタディ自動実行】&lt;/strong&gt;をお届けします！&lt;br/&gt;
            Google Antigravity や Claude Code などの最先端AIエージェントに「Issue #101 のバグ修正用ブランチを切り、C#コードを修正してテストを通し、PR（プルリクエスト）を作って」と一括指示する自動化シミュレーションを徹底解説。&lt;br/&gt;
            人間が手を動かしていた定型業務をAIが完全自律代行する近未来の開発スタイルを体験しましょう！
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/1791111503627724423/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-25case-5.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/1791111503627724423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/1791111503627724423'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-25case-5.html' title='【Day 25】【Case 5】仕様変更・機能のリリース順序入れ替え（チェリーピック）'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/14hpFOtuGHHYz6ZxLAhxekYBaQILIeXod=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-4383842111647684763</id><published>2026-10-23T09:20:49.898+09:00</published><updated>2026-10-23T09:20:49.898+09:00</updated><title type='text'>【Day 27】コンテナを破棄するとデータが消える！？ データの永続化の原理 〜書き込み可能レイヤー（OverlayFS）の消滅、ステートレス設計、Volume vs Bind Mount の使い分け、C#ログ・画像保存設計〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1GNRuA7vXfzYqrrX-hkUfnmM5_eCtF1Lr&quot; alt=&quot;Day 27 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 27: コンテナを破棄するとデータが消える！？ データの永続化の原理&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 導入メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: linear-gradient(135deg, #e0f2fe 0%, #f0fdf4 100%); border-left: 6px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0; box-shadow: 0 4px 12px rgba(13,183,237,0.08);&quot;&gt;
        &lt;div style=&quot;font-size: 32px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;font-size: 15.5px; color: #0f172a;&quot;&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; font-weight: bold; color: #0369a1; font-size: 17px;&quot;&gt;「コンテナを再ビルドしたら、テスト登録したDBレコードや画像が全部消えた…！？」と焦ったことはありませんか？&lt;/p&gt;
            &lt;p style=&quot;margin: 0; line-height: 1.8;&quot;&gt;
                Windows Server、Hyper-V、VMwareなどで長年インフラや社内システムを構築してきたエンジニアにとって、「仮想マシンのCドライブやDドライブに保存したファイルは、OSを再起動してもマシンを作り直さない限りそのまま残る」というのが当たり前の常識でした。&lt;br/&gt;
                しかしDockerのコンテナは、&lt;strong&gt;「いつでも破棄して作り直せるエフェメラル（使い捨て）なプロセス」&lt;/strong&gt;として設計されています。そのため、何も設定せずにコンテナ内でデータベースを動かしたり、ユーザーがアップロードしたファイルを保存したりすると、コンテナを破棄（&lt;code&gt;docker rm&lt;/code&gt; や &lt;code&gt;docker compose down&lt;/code&gt;）した瞬間に、&lt;strong&gt;すべてのデータが宇宙の彼方へ消滅&lt;/strong&gt;してしまいます。&lt;br/&gt;
                本講義では、なぜコンテナ内のデータが消えるのかという内部アーキテクチャ（OverlayFS / 書き込み可能レイヤー）を解き明かし、データをホストOS側へ安全に逃がして永続化する &lt;strong&gt;「ボリューム（Volume）」と「バインドマウント（Bind Mount）」の原理・使い分け・C#設計パターン&lt;/strong&gt; を完全マスターします！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 目次セクション --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 12px; font-size: 17px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 4px; padding: 2px 8px; font-size: 13px; margin-right: 10px;&quot;&gt;INDEX&lt;/span&gt;
            本日の講義カリキュラム
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #475569; font-size: 15px; line-height: 2;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;第1章: なぜコンテナを消すとデータが消えるのか？ 〜OverlayFSと書き込み可能レイヤーの構造〜&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第2章: コンテナの「ステートレス（無状態）原則」とデータの寿命管理&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第3章: 永続化の2大手法「ボリューム（Volume）」vs「バインドマウント（Bind Mount）」徹底比較&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第4章: ホスト退避アーキテクチャの動作メカニズム&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第5章: C#/.NET現場におけるデータ保存設計（ログ・アップロードファイル・DB）&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;第6章: 本日のまとめと次回予告（Day 28: SQL Serverボリューム実践）&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第1章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第1章: なぜコンテナを消すとデータが消えるのか？ 〜OverlayFSと書き込み可能レイヤーの構造〜&lt;/h2&gt;

    &lt;p&gt;
        従来の仮想マシン（VMwareやHyper-V）では、ゲストOSのディスク全体が1つの仮想ハードディスクファイル（&lt;code&gt;.vhdx&lt;/code&gt; や &lt;code&gt;.vmdk&lt;/code&gt;）としてホスト上に実体を持っています。そのため、VMの電源を切っても、ゲストOS内で作成したファイルはディスク上に永久に保存されます。
    &lt;/p&gt;
    &lt;p&gt;
        これに対し、Dockerコンテナのファイルシステムは &lt;strong&gt;「多層構造（UnionFS / OverlayFS）」&lt;/strong&gt; という特殊な仕組みで動いています。
    &lt;/p&gt;

    &lt;!-- コールアウト: レイヤー構造 --&gt;
    &lt;div style=&quot;background: #f1f5f9; border-left: 4px solid #512bd4; padding: 16px 20px; border-radius: 6px; margin: 20px 0;&quot;&gt;
        &lt;strong style=&quot;color: #3b0764; font-size: 16px;&quot;&gt;💡 Dockerのファイルシステム多層構造の正体&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.8;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;イメージ層（Image Layers: Read-Only）:&lt;/strong&gt; &lt;code&gt;Dockerfile&lt;/code&gt; でビルドされた各命令（&lt;code&gt;FROM&lt;/code&gt;, &lt;code&gt;COPY&lt;/code&gt;, &lt;code&gt;RUN&lt;/code&gt; 等）の成果物。&lt;strong&gt;完全に読み取り専用（イミュータブル）&lt;/strong&gt;であり、複数のコンテナ間で共有されます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;コンテナ層（Container Layer: Read-Write）:&lt;/strong&gt; コンテナが起動した瞬間に、イメージ層の最上位に被せられる &lt;strong&gt;極薄の書き込み可能レイヤー&lt;/strong&gt;。コンテナ内で新しく作成されたファイルや変更されたファイルは、すべてこのレイヤーにのみ記録されます。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        ここが最大のポイントです。コンテナを停止（&lt;code&gt;docker stop&lt;/code&gt;）しただけであれば、コンテナ層はまだ保持されているためデータは消えません。しかし、&lt;strong&gt;コンテナを破棄（&lt;code&gt;docker rm&lt;/code&gt; や &lt;code&gt;docker compose down&lt;/code&gt;）した瞬間、このコンテナ層はコンテナプロセスと一緒に綺麗さっぱり消滅&lt;/strong&gt; します。
    &lt;/p&gt;
    &lt;p&gt;
        下層のイメージ層は無傷ですが、コンテナ層に書かれていた「アプリケーションが書き込んだログ」「登録したDBレコード」「ユーザーがアップロードした画像」は、跡形もなく消え去ってしまうのです。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1kO1z5MdsP4yj9u21or9Stan9j03qttx7&quot; alt=&quot;コンテナ破棄でデータが消える理由&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】イメージ層（読み取り専用）とコンテナ層（書き込み層）の分離と破棄時のデータ消失メカニズム&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 第2章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第2章: コンテナの「ステートレス（無状態）原則」とデータの寿命管理&lt;/h2&gt;

    &lt;p&gt;
        「それなら、コンテナを破棄してもコンテナ層を自動保存してくれれば便利なのでは？」と思うかもしれません。しかし、これこそが &lt;strong&gt;クラウドネイティブ・コンテナ設計の大原則「ステートレス（無状態）設計」&lt;/strong&gt; です。
    &lt;/p&gt;

    &lt;div style=&quot;background: #fffbeb; border: 1px solid #fef3c7; border-left: 5px solid #f59e0b; padding: 18px 22px; border-radius: 8px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #92400e; font-size: 16px;&quot;&gt;⚠️ なぜコンテナ内に状態（データ）を持ってはいけないのか？&lt;/h4&gt;
        &lt;ol style=&quot;margin: 0; padding-left: 20px; color: #78350f; line-height: 1.8;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;いつでも使い捨てて水平スケーリングするため:&lt;/strong&gt; アクセス増に伴いコンテナを1個から10個へスケールアウトするとき、各コンテナがローカルにデータを持っているとデータ不整合が発生します。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;ゼロダウンタイムでバージョンアップするため:&lt;/strong&gt; アプリの新バージョンをデプロイする際、「旧コンテナを破棄して新コンテナを起動する」というローリングアップデートを行います。コンテナ内にデータがあると、デプロイのたびにデータが失われてしまいます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;障害時の自動復旧（自己修復）のため:&lt;/strong&gt; コンテナがハングアップした場合、KubernetesやDocker Composeはコンテナを殺して即座に別ノードで新しいコンテナを立ち上げます。&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;p&gt;
        したがって、コンテナアーキテクチャでは &lt;strong&gt;「コンテナ自体はいつでも死んで良いエフェメラルな存在とし、保持すべきデータはコンテナの外（ホストOSやクラウドストレージ）に逃がす」&lt;/strong&gt; のが絶対の鉄則となります。
    &lt;/p&gt;

    &lt;!-- 第3章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第3章: 永続化の2大手法「ボリューム（Volume）」vs「バインドマウント（Bind Mount）」徹底比較&lt;/h2&gt;

    &lt;p&gt;
        データをコンテナ外部へ逃がして永続化するための手法として、Dockerには &lt;strong&gt;「ボリューム（Volume）」&lt;/strong&gt; と &lt;strong&gt;「バインドマウント（Bind Mount）」&lt;/strong&gt; という2大マウント方式が用意されています。
    &lt;/p&gt;

    &lt;div style=&quot;display: flex; gap: 20px; margin: 25px 0; flex-wrap: wrap;&quot;&gt;
        &lt;!-- ボリュームカード --&gt;
        &lt;div style=&quot;flex: 1; min-width: 280px; background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 20px; box-shadow: 0 2px 6px rgba(0,0,0,0.04);&quot;&gt;
            &lt;div style=&quot;display: flex; align-items: center; margin-bottom: 12px;&quot;&gt;
                &lt;span style=&quot;font-size: 24px; margin-right: 8px;&quot;&gt;🗄️&lt;/span&gt;
                &lt;h3 style=&quot;margin: 0; color: #166534; font-size: 18px;&quot;&gt;ボリューム（Volume）&lt;/h3&gt;
            &lt;/div&gt;
            &lt;p style=&quot;font-size: 14.5px; color: #14532d; line-height: 1.7; margin: 0 0 12px 0;&quot;&gt;
                &lt;strong&gt;Docker自身が管理する専用ストレージ領域&lt;/strong&gt;（Linuxホスト上の &lt;code&gt;/var/lib/docker/volumes/&lt;/code&gt; 配下）。
            &lt;/p&gt;
            &lt;ul style=&quot;margin: 0; padding-left: 18px; font-size: 14px; color: #166534; line-height: 1.7;&quot;&gt;
                &lt;li&gt;ホストのファイル構造を意識不要（Docker CLIで管理）&lt;/li&gt;
                &lt;li&gt;I/Oパフォーマンスが極めて高く安定&lt;/li&gt;
                &lt;li&gt;パーミッション問題が起きにくい&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;推奨用途:&lt;/strong&gt; データベース（SQL Server, PostgreSQL, MySQL）、永続化ストレージ&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/div&gt;

        &lt;!-- バインドマウントカード --&gt;
        &lt;div style=&quot;flex: 1; min-width: 280px; background: #faf5ff; border: 1px solid #e9d5ff; border-radius: 8px; padding: 20px; box-shadow: 0 2px 6px rgba(0,0,0,0.04);&quot;&gt;
            &lt;div style=&quot;display: flex; align-items: center; margin-bottom: 12px;&quot;&gt;
                &lt;span style=&quot;font-size: 24px; margin-right: 8px;&quot;&gt;🔄&lt;/span&gt;
                &lt;h3 style=&quot;margin: 0; color: #6b21a8; font-size: 18px;&quot;&gt;バインドマウント（Bind Mount）&lt;/h3&gt;
            &lt;/div&gt;
            &lt;p style=&quot;font-size: 14.5px; color: #581c87; line-height: 1.7; margin: 0 0 12px 0;&quot;&gt;
                &lt;strong&gt;ホストPCの特定ディレクトリをコンテナ内に直結&lt;/strong&gt; する方式（&lt;code&gt;./src:/app/src&lt;/code&gt; 等）。
            &lt;/p&gt;
            &lt;ul style=&quot;margin: 0; padding-left: 18px; font-size: 14px; color: #6b21a8; line-height: 1.7;&quot;&gt;
                &lt;li&gt;ホスト側でファイルを編集すると即座にコンテナ内に反映&lt;/li&gt;
                &lt;li&gt;コンテナ側が生成したファイルをホストから直接閲覧可能&lt;/li&gt;
                &lt;li&gt;OS間（Windows/Linux）のパーミッションや改行コードに注意&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;推奨用途:&lt;/strong&gt; ローカル開発時のソースコード同期（ホットリロード）、設定ファイル注入&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 比較表 --&gt;
    &lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 25px 0; font-size: 14.5px;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background: #0f172a; color: #ffffff;&quot;&gt;
                &lt;th style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; text-align: left;&quot;&gt;比較項目&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; text-align: left; width: 45%;&quot;&gt;ボリューム（Volume）&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; text-align: left; width: 45%;&quot;&gt;バインドマウント（Bind Mount）&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;保存場所&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;Docker管理下の領域（ホストユーザーから直接触らない）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;ホストPC上の任意のディレクトリ（開発者が直接編集）&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;移植性（ポータビリティ）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;◎ 非常に高い（Windows/Mac/Linux問わず同一設定で動作）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;△ ホストのディレクトリ構造に依存（相対パス推奨）&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;I/O速度（WSL2上）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;◎ ネイティブLinux速度（超高速）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;○ WSL2領域なら高速（Windows側Cドライブ直結は遅延あり）&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;主なユースケース&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;DBデータ永続化、ログ集約、本番データ保管&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;ローカル開発でのコード編集・ホットリロード（dotnet watch）&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1HfX-q7pE-dzAGqoLlmZdArI9v3gAzY14&quot; alt=&quot;永続化の2大手法&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】ボリューム（Volume: Docker管理専用領域） vs バインドマウント（Bind Mount: ホストフォルダ直結）の徹底比較&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 第4章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第4章: ホスト退避アーキテクチャの動作メカニズム&lt;/h2&gt;

    &lt;p&gt;
        「コンテナを破棄してもデータが消えない」というのは、具体的に内部でどのような動きをしているのでしょうか？&lt;br/&gt;
        その秘密は、&lt;strong&gt;「コンテナ内の特定ディレクトリへのアクセスを、OverlayFSの書き込み可能レイヤーを通さずに、ホスト側のストレージへバイパス（直結）する」&lt;/strong&gt; というマウント機構にあります。
    &lt;/p&gt;

    &lt;!-- 3ステップ解説 --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 22px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 14px 0; color: #0369a1; font-size: 16px;&quot;&gt;🔄 ホスト退避によるデータ保護の3ステップ&lt;/h4&gt;
        &lt;div style=&quot;display: flex; flex-direction: column; gap: 14px;&quot;&gt;
            &lt;div style=&quot;display: flex; align-items: flex-start;&quot;&gt;
                &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 50%; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: bold; margin-right: 12px; flex-shrink: 0;&quot;&gt;1&lt;/span&gt;
                &lt;div&gt;
                    &lt;strong style=&quot;color: #0f172a;&quot;&gt;コンテナ書き込み:&lt;/strong&gt; アプリケーション（例: C# Web API）がコンテナ内の &lt;code&gt;/app/data&lt;/code&gt; や &lt;code&gt;/var/opt/mssql/data&lt;/code&gt; にファイルを書き込みます。
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div style=&quot;display: flex; align-items: flex-start;&quot;&gt;
                &lt;span style=&quot;background: #512bd4; color: #ffffff; border-radius: 50%; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: bold; margin-right: 12px; flex-shrink: 0;&quot;&gt;2&lt;/span&gt;
                &lt;div&gt;
                    &lt;strong style=&quot;color: #0f172a;&quot;&gt;ホスト領域へ退避:&lt;/strong&gt; マウント設定により、データはエフェメラルなコンテナ層を素通りし、ホストOS上のボリューム領域へダイレクトに物理保存されます。
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div style=&quot;display: flex; align-items: flex-start;&quot;&gt;
                &lt;span style=&quot;background: #10b981; color: #ffffff; border-radius: 50%; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: bold; margin-right: 12px; flex-shrink: 0;&quot;&gt;3&lt;/span&gt;
                &lt;div&gt;
                    &lt;strong style=&quot;color: #0f172a;&quot;&gt;再作成・同一データ再接続:&lt;/strong&gt; &lt;code&gt;docker compose down&lt;/code&gt; で古いコンテナを削除し、最新イメージで &lt;code&gt;docker compose up&lt;/code&gt; して新コンテナを立ち上げても、同じボリュームを指定すれば、前回のデータにそのまま再接続されます！
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1e4noVWuVVUmA9OSWPyt5yrzD1zUn4XEr&quot; alt=&quot;ホスト退避によるデータ保護&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】コンテナ外のホスト領域へデータを逃がし、コンテナを再作成しても同一データを再接続する3ステップ&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 第5章 --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第5章: C#/.NET現場におけるデータ保存設計（ログ・アップロードファイル・DB）&lt;/h2&gt;

    &lt;p&gt;
        それでは、C#/.NETの開発現場において、どのようなデータをどこに保存すべきか、実践的なアーキテクチャ設計を見ていきましょう。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #0369a1; font-size: 18px; margin-top: 30px;&quot;&gt;① 実例: Serilogによるログ出力設計（STDOUT vs ボリューム）&lt;/h3&gt;
    &lt;p&gt;
        .NET Framework時代のIIS開発では、&lt;code&gt;C:\inetpub\logs\log.txt&lt;/code&gt; などのローカルファイルにログを出力するのが一般的でした。&lt;br/&gt;
        しかしコンテナの世界におけるベストプラクティス（The Twelve-Factor App原則）は &lt;strong&gt;「ログはファイルに書かず、すべて標準出力（Console / STDOUT）に流す」&lt;/strong&gt; です。
    &lt;/p&gt;

    &lt;!-- コード例: Program.cs Serilog --&gt;
    &lt;div style=&quot;background: #1e293b; border-radius: 8px; padding: 18px 20px; margin: 20px 0; overflow-x: auto;&quot;&gt;
        &lt;div style=&quot;color: #94a3b8; font-size: 12.5px; margin-bottom: 8px; font-family: Consolas, monospace;&quot;&gt;Program.cs (C# 12 / .NET 8)&lt;/div&gt;
        &lt;pre style=&quot;margin: 0; color: #f8fafc; font-family: Consolas, Monaco, monospace; font-size: 14px; line-height: 1.6;&quot;&gt;&lt;code&gt;using Serilog;

var builder = WebApplication.CreateBuilder(args);

// コンテナベストプラクティス: ログは標準出力（Console）へ流す
builder.Host.UseSerilog((ctx, lc) =&gt; lc
    .WriteTo.Console()
    // コンプライアンス等でファイル保存が必須な場合のみ、ボリュームマウントされたパスを指定
    .WriteTo.File(&quot;/app/logs/application-.log&quot;, rollingInterval: RollingInterval.Day));

var app = builder.Build();
app.MapGet(&quot;/&quot;, () =&gt; &quot;Hello Docker Persistence!&quot;);
app.Run();&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;

    &lt;p&gt;
        標準出力に流されたログは、Dockerのログドライバーによって自動的に管理され、&lt;code&gt;docker compose logs -f&lt;/code&gt; やクラウド（AWS CloudWatch, Azure Log Analytics等）へシームレスに集約されます。もしファイル出力が必要な場合は、&lt;code&gt;/app/logs&lt;/code&gt; をボリュームにマウントします。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #0369a1; font-size: 18px; margin-top: 30px;&quot;&gt;② 実例: ユーザーがアップロードした画像の永続化&lt;/h3&gt;
    &lt;p&gt;
        ECサイトや社内システムで、ユーザーがWeb画面からアップロードした商品画像やPDFファイルを &lt;code&gt;wwwroot/uploads&lt;/code&gt; に保存するケースです。&lt;br/&gt;
        このディレクトリをコンテナ内に置いたままにすると、デプロイのたびにユーザー画像が全滅します！以下のように &lt;code&gt;docker-compose.yml&lt;/code&gt; で名前付きボリューム（Named Volume）を定義して救出します。
    &lt;/p&gt;

    &lt;!-- docker-compose.yml 例 --&gt;
    &lt;div style=&quot;background: #1e293b; border-radius: 8px; padding: 18px 20px; margin: 20px 0; overflow-x: auto;&quot;&gt;
        &lt;div style=&quot;color: #94a3b8; font-size: 12.5px; margin-bottom: 8px; font-family: Consolas, monospace;&quot;&gt;docker-compose.yml&lt;/div&gt;
        &lt;pre style=&quot;margin: 0; color: #f8fafc; font-family: Consolas, Monaco, monospace; font-size: 14px; line-height: 1.6;&quot;&gt;&lt;code&gt;services:
  web-api:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - &quot;5000:8080&quot;
    volumes:
      # アップロード画像フォルダを名前付きボリュームにマウント！
      - app-uploads:/app/wwwroot/uploads
      # ログ出力先も永続化
      - app-logs:/app/logs

# 最下部でボリュームを明示的に宣言
volumes:
  app-uploads:
    driver: local
  app-logs:
    driver: local&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0369a1; font-size: 18px; margin-top: 30px;&quot;&gt;③ Git管理（静的コード）とボリューム（動的データ）の明確な住み分け&lt;/h3&gt;
    &lt;p&gt;
        チーム開発で最もやってはいけない重大な事故が、&lt;strong&gt;「データベースのファイルやログ、アップロード画像などの巨大バイナリをGitにコミットしてしまうこと」&lt;/strong&gt; です。&lt;br/&gt;
        現場での明確な住み分けルールを以下のマトリクスにまとめました。
    &lt;/p&gt;

    &lt;!-- 住み分け表 --&gt;
    &lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0; font-size: 14.5px;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background: #0f172a; color: #ffffff;&quot;&gt;
                &lt;th style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; text-align: left;&quot;&gt;対象データ&lt;/th&gt;
                &lt;th style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; text-align: left;&quot;&gt;管理場所&lt;/th&gt;
                &lt;th style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; text-align: left;&quot;&gt;理由・運用ルール&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;C#ソースコード（.cs, .csproj）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #512bd4; font-weight: bold;&quot;&gt;Git（リポジトリ）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;アプリケーションの設計図。差分管理とPRレビューの対象。&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;Dockerfile / docker-compose.yml&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #512bd4; font-weight: bold;&quot;&gt;Git（リポジトリ）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;インフラのコード化（IaC）。チーム全員で同一環境を再現。&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;環境設定テンプレート（.env.example）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #512bd4; font-weight: bold;&quot;&gt;Git（リポジトリ）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;キー名のみをGit管理（機密値が入った実.envは除外）。&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;SQL Server DB実ファイル（.mdf / .ldf）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #0db7ed; font-weight: bold;&quot;&gt;ボリューム（Volume）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;絶対にGitへコミット禁止（リポジトリ破壊の元）。Volumeで安全保持。&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;ユーザーアップロード画像・PDF&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1; color: #0db7ed; font-weight: bold;&quot;&gt;ボリューム（Volume）&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;動的に増減するバイナリデータ。&lt;code&gt;.gitignore&lt;/code&gt; で確実に除外。&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1gFHjCu5U18L01Ysk5ZWc8kDrjA7hxhQJ&quot; alt=&quot;C#現場のデータ分離設計&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】Git管理（静的コード・設定雛形）とボリューム（動的データ・ログ・DB）の境界線マトリクス&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 第6章: まとめ --&gt;
    &lt;h2 style=&quot;color: #0f172a; border-bottom: 2px solid #0db7ed; padding-bottom: 8px; margin-top: 45px; font-size: 22px;&quot;&gt;第6章: 本日のまとめと次回予告&lt;/h2&gt;

    &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 22px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 14px; font-size: 18px;&quot;&gt;📌 本日の重要ポイントまとめ&lt;/h3&gt;
        &lt;ol style=&quot;margin: 0; padding-left: 22px; color: #334155; line-height: 1.9; font-size: 15.5px;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;コンテナのファイルシステムは2層構造:&lt;/strong&gt; 読み取り専用の「イメージ層」の上に、使い捨ての「コンテナ層（書き込み可能）」が乗っている。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;コンテナ破棄で書き込み層は消滅:&lt;/strong&gt; &lt;code&gt;docker rm&lt;/code&gt; や &lt;code&gt;compose down&lt;/code&gt; を行うとコンテナ層ごと消えるため、内部のデータは消失する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;ステートレス設計の大原則:&lt;/strong&gt; コンテナ自体は「いつでも破棄・再生成できる無状態」を保ち、保持すべきデータはホスト側に逃がす。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;永続化の2大巨頭:&lt;/strong&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;strong&gt;ボリューム（Volume）:&lt;/strong&gt; Docker管理領域。高速・安全でDBや本番データの永続化に最適。&lt;/li&gt;
                    &lt;li&gt;&lt;strong&gt;バインドマウント（Bind Mount）:&lt;/strong&gt; ホストフォルダ直結。ローカル開発時のソースコード同期（ホットリロード）に最適。&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;GitとVolumeの厳格な分離:&lt;/strong&gt; コードやDockerfileはGitで管理し、DBデータやログ、アップロード画像はVolumeに逃がして &lt;code&gt;.gitignore&lt;/code&gt; で徹底除外する。&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;!-- 次回予告カード --&gt;
    &lt;div style=&quot;background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); color: #ffffff; border-radius: 8px; padding: 22px 24px; margin: 35px 0; box-shadow: 0 4px 14px rgba(0,0,0,0.15);&quot;&gt;
        &lt;div style=&quot;display: flex; align-items: center; margin-bottom: 10px;&quot;&gt;
            &lt;span style=&quot;font-size: 22px; margin-right: 10px;&quot;&gt;🚀&lt;/span&gt;
            &lt;span style=&quot;color: #38bdf8; font-weight: bold; font-size: 14px; letter-spacing: 1px;&quot;&gt;NEXT STEP&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3 style=&quot;margin: 0 0 10px 0; color: #ffffff; font-size: 19px;&quot;&gt;次回 【Day 28】ボリューム（Named Volume）によるSQL Serverデータの安全な永続化&lt;/h3&gt;
        &lt;p style=&quot;margin: 0; color: #94a3b8; font-size: 14.5px; line-height: 1.7;&quot;&gt;
            原理を理解したところで、次回はいよいよ実務での実践編！&lt;br/&gt;
            SQL Serverコンテナのデータディレクトリ（&lt;code&gt;/var/opt/mssql/data&lt;/code&gt;）をNamed Volumeにマウントし、コンテナを破棄・再ビルドしてもテストデータが1件も失われない堅牢なDB開発環境を構築します。お楽しみに！
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/4383842111647684763/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-27-overlayfsvolume-vs-bind-mount-c.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4383842111647684763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4383842111647684763'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-27-overlayfsvolume-vs-bind-mount-c.html' title='【Day 27】コンテナを破棄するとデータが消える！？ データの永続化の原理 〜書き込み可能レイヤー（OverlayFS）の消滅、ステートレス設計、Volume vs Bind Mount の使い分け、C#ログ・画像保存設計〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1GNRuA7vXfzYqrrX-hkUfnmM5_eCtF1Lr=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-4350464692634907152</id><published>2026-10-22T18:12:06.026+09:00</published><updated>2026-10-22T18:12:06.026+09:00</updated><title type='text'>【Day 24】【Case 4】本番障害！ 緊急バグ修正（Hotfix）の完全手順</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/16vf0iT-raXrUO3xpFKKhX8wJ5QbnBQ47&quot; alt=&quot;Day 24 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 24】本番障害！ 緊急バグ修正（Hotfix）の完全手順&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 23では、製品リリースの総仕上げとして、mainマージ、注釈付きタグ（Annotated Tag）打刻、そしてdevelopへのマージバックによる安定バージョンの凍結サイクルを学びました。&lt;br/&gt;
            本日のDay 24は、現場のエンジニアが最も緊張感を強いられる実践ケーススタディ——&lt;strong&gt;【本番障害！ 緊急バグ修正（Hotfix）の完全手順】&lt;/strong&gt;を徹底講義します！&lt;br/&gt;
            金曜日の夕方やサービス公開直後、「本番環境でユーザーの特定操作によってC#アプリが突然クラッシュした！」「至急パッチを当ててほしい！」という緊急アラートが鳴り響いた経験は、ベテランエンジニアなら誰しも一度はあるはずです。&lt;br/&gt;
            Subversion (SVN) や Visual SourceSafe (VSS) で開発していた現場では、中央のトランク（trunk）にすでに次期バージョンの未完成コードや実験的コードがコミットされているため、本番修正を行うには「過去のリビジョンに戻してコードを手動で修正し、本番用バイナリをビルドしたあと、トランクにも手動で差分をコピペする」という恐ろしい二重管理を強いられていました。その結果、本番に未完成機能が誤って混入したり、トランクへの反映漏れで次のリリース時に直したはずのバグが復活する（先祖返り）大事故が日常茶飯事でした。&lt;br/&gt;
            しかしGitなら、本番稼働中の安定コミット（mainブランチまたはv1.0.0タグ）から直接&lt;strong&gt;「hotfix/* ブランチ」&lt;/strong&gt;をわずか1秒で切り出すことができます！&lt;br/&gt;
            現在developブランチで進んでいる次期機能の開発中コードには指一本触れず、完全に隔離された安全な環境で最小限の緊急パッチを作成・検証できます。そして即座にmainへマージして新パッチタグ（v1.0.1）を打ち、最後にdevelopへもマージバックすることで、先祖返りを100%防止できます。&lt;br/&gt;
            本日は、Git CLI / TortoiseGitでのhotfix運用手順、C#で最も頻発する「NullReferenceException」の安全な防御的修正パターン、緊急時こそ単体テスト（&lt;code&gt;dotnet test&lt;/code&gt;）を書くべき理由、そしてマージバック忘れを防ぐ鉄壁のチェックリストまで、現場の最前線で戦うエンジニアのための「火消しの極意」を完全網羅でお届けします！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        本番障害における最優先ミッションは、&lt;strong&gt;「稼働中のサービスを最速で正常復旧させること」&lt;/strong&gt;と&lt;strong&gt;「開発中の未完成コードを決して本番に混入させないこと」&lt;/strong&gt;の2つを同時に達成することです。&lt;br/&gt;
        緊急事態だからといって焦って雑な修正を行えば、別の致命的なバグを引き起こす「二次災害」に繋がります。&lt;br/&gt;
        GitのHotfix（ホットフィックス）ワークフローを正しくマスターすれば、緊迫した障害現場でも冷静沈着に、寸分の狂いもなく安全なパッチリリースを完了させることができます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;SVNの「開発中コード混入の恐怖・手動コピペ事故」とGitの「クリーンなhotfix隔離分岐」の違いを理解する&lt;/li&gt;
            &lt;li&gt;本番コミット（main）から &lt;code&gt;hotfix/1.0.1&lt;/code&gt; ブランチを正確に切り出す手順を習得する&lt;/li&gt;
            &lt;li&gt;C#における &lt;code&gt;NullReferenceException&lt;/code&gt; の安全な修正（Null条件演算子 &lt;code&gt;?.&lt;/code&gt; / Null合体演算子 &lt;code&gt;??&lt;/code&gt;）と、単体テスト（&lt;code&gt;dotnet test&lt;/code&gt;）による二次災害防止を徹底する&lt;/li&gt;
            &lt;li&gt;mainブランチへの安全なマージ（&lt;code&gt;git merge --no-ff&lt;/code&gt;）とパッチバージョンタグ（&lt;code&gt;v1.0.1&lt;/code&gt;）の打刻手順をマスターする&lt;/li&gt;
            &lt;li&gt;developブランチへのマージバックを完了させ、次期リリースでの先祖返り（バグ復活）を100%防止する&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: SVN修正地獄 vs Git hotfix --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】SVNの修正地獄 vs Gitの緊急hotfix分岐：なぜGitは安全に火消しができるのか？&lt;/h2&gt;
    &lt;p&gt;
        まずは、SVNなどの集中型バージョン管理とGitにおける「本番緊急修正」のアプローチの根本的な違いを確認しましょう。
    &lt;/p&gt;

    &lt;!-- 図解① --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1DWtOw5jH5NikbWM-5fetYOeNV3Q-V5lM&quot; alt=&quot;SVN修正地獄 vs Git緊急hotfix分岐&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】SVNの「開発中コード混入の恐怖（手動コピペ事故）」vs Gitの「mainから直接hotfix分岐（クリーン＆完全隔離）」&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        集中型バージョン管理（SVN / VSS）では、開発チーム全員が共有の &lt;code&gt;trunk&lt;/code&gt; で作業を続けています。製品バージョン1.0.0をリリースした直後から、すでにメンバーは次期バージョン2.0.0に向けた新機能コードをtrunkにコミットし始めています。&lt;br/&gt;
        そんな中で本番障害が発生した場合、エンジニアは次のような「地獄の二者択一」を迫られていました。
    &lt;/p&gt;

    &lt;div style=&quot;background: #fff1f2; border-left: 5px solid #e11d48; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #be123c; font-size: 16.5px;&quot;&gt;💥 SVN時代に頻発した本番修正トラウマ&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85; color: #4c0519;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;未完成コード混入の恐怖:&lt;/strong&gt; trunkの最新状態で急いでバグ修正してビルドした結果、開発途中で動かないはずの新機能や未検証ロジックが本番に誤って混入してしまう大事故。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;手動コピペの反映漏れ（先祖返り）:&lt;/strong&gt; 過去のリリースリビジョンをローカルにチェックアウトしてバグ修正し、本番バイナリを作成。しかし「trunk側にも同じ修正を当てる」のを手動コピペで行っていたため、コピペ漏れが発生。3ヶ月後の定期リリースで、以前直したはずのバグが突如復活する悪夢。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        これに対し、Gitでは&lt;strong&gt;「mainブランチ（またはv1.0.0タグ）から直接hotfixブランチを切り出す」&lt;/strong&gt;ことができます。&lt;br/&gt;
        ブランチの作成は単に特定コミットへのポインタを新設するだけ（所要時間0.1秒、容量数バイト）なので、developで進んでいる開発中コードから100%クリーンに隔離された安全な作業環境が手に入ります。開発中の未完成コードが混ざる危険性はゼロです。
    &lt;/p&gt;

    &lt;!-- セクション③: hotfixワークフロー完全手順 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】hotfixブランチ作成と本番反映の3ステップ完全手順&lt;/h2&gt;
    &lt;p&gt;
        本番障害発生からパッチリリースまでの標準的なGitワークフローを見ていきましょう。
    &lt;/p&gt;

    &lt;!-- 図解② --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/14kXOsGHI1iu3q3Yffi9ihGAxRvFbAKRj&quot; alt=&quot;hotfixブランチ作成と本番反映の3ステップ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】mainからのhotfix切り出し・最小修正コミット・mainマージ＆v1.0.1パッチタグ打刻の3ステップ&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;ステップ1: 本番（main）から hotfix ブランチを切り出す&lt;/h3&gt;
    &lt;p&gt;
        最新の安定コミットである &lt;code&gt;main&lt;/code&gt;（またはタグ &lt;code&gt;v1.0.0&lt;/code&gt;）を指定して、緊急修正用ブランチを作成します。命名規則は &lt;code&gt;hotfix/1.0.1&lt;/code&gt; や &lt;code&gt;hotfix/issue-404&lt;/code&gt; など、修正対象バージョンやチケット番号を明確にします。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# mainブランチを最新化&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch main&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; pull origin main&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# mainからhotfixブランチを作成して切り替え&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch -c hotfix/1.0.1 main
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;ステップ2: 最小限のバグ修正コミット（スコープ厳格制限）&lt;/h3&gt;
    &lt;p&gt;
        Hotfixブランチで行う作業は、&lt;strong&gt;「障害の直接原因となった箇所の修正」だけに厳格に絞り込みます。&lt;/strong&gt;&lt;br/&gt;
        「ついでにコードのリファクタリングをしよう」「コードフォーマッターを一括適用しよう」といった変更は&lt;strong&gt;絶対に厳禁&lt;/strong&gt;です。差分行数が膨らむとレビューが遅れ、新たな潜在的バグを生むリスクが激増します。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;ステップ3: mainへのマージ＆注釈付きパッチタグ打刻&lt;/h3&gt;
    &lt;p&gt;
        修正と検証が完了したら、&lt;code&gt;main&lt;/code&gt; ブランチへ &lt;code&gt;--no-ff&lt;/code&gt; オプション付きでマージし、パッチバージョン番号（例: &lt;code&gt;v1.0.1&lt;/code&gt;）の注釈付きタグを打ってプッシュします。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 1. mainへ移動してhotfixを統合（マージコミットを明示）&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch main&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; merge --no-ff hotfix/1.0.1 -m &lt;span style=&quot;color: #fde047;&quot;&gt;&quot;Merge hotfix/1.0.1 into main (Fix NullReferenceException)&quot;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 2. パッチバージョンの注釈付きタグを打刻&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; tag -a v1.0.1 -m &lt;span style=&quot;color: #fde047;&quot;&gt;&quot;Hotfix v1.0.1: Fix NullReferenceException in UserProfile&quot;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 3. mainブランチとタグをリモートリポジトリへ即時プッシュ&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin main&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin v1.0.1
    &lt;/div&gt;

    &lt;!-- セクション④: C#現場での緊急パッチとNull安全性 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【図解】C#現場での緊急パッチとNull安全性：二次災害を防ぐプロの技&lt;/h2&gt;
    &lt;p&gt;
        C#アプリケーションの本番障害で圧倒的第1位を占めるのが、言わずと知れた &lt;code&gt;System.NullReferenceException&lt;/code&gt;（いわゆる「ぬるぽ」）です。&lt;br/&gt;
        具体的なコード例とともに、安全な防御的プログラミングとテスト手法を確認しましょう。
    &lt;/p&gt;

    &lt;!-- 図解③ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1OQpQW-GsKyOyd35oMo0k43KMd9GpTrQA&quot; alt=&quot;C#現場での緊急パッチとNull安全性&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】C#現場でのNullReferenceException緊急パッチ適用と単体テスト（dotnet test）による二次災害防止&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;クラッシュコード（Before）と安全な修正コード（After）&lt;/h3&gt;
    &lt;p&gt;
        例えば、会員プロフィールの住所郵便番号を取得するサービスで、プロフィール未登録ユーザーのアクセス時にクラッシュが発生していたケースです。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f1f5f9; border-radius: 6px; padding: 18px; margin: 20px 0;&quot;&gt;
        &lt;strong style=&quot;color: #dc2626;&quot;&gt;❌ 障害発生コード（Before）: Nullチェック欠落によるクラッシュ&lt;/strong&gt;
        &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14px; margin-top: 8px;&quot;&gt;
            &lt;span style=&quot;color: #93c5fd;&quot;&gt;public string&lt;/span&gt; &lt;span style=&quot;color: #67e8f9;&quot;&gt;GetUserPostalCode&lt;/span&gt;(&lt;span style=&quot;color: #93c5fd;&quot;&gt;User&lt;/span&gt; user)&lt;br/&gt;
            {&lt;br/&gt;
            &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;// user.Profile が null の場合、アクセスした瞬間に NullReferenceException でプロセス死亡！&lt;/span&gt;&lt;br/&gt;
            &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f43f5e; font-weight: bold;&quot;&gt;return user.Profile.Address.PostalCode;&lt;/span&gt;&lt;br/&gt;
            }
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #ecfdf5; border-radius: 6px; padding: 18px; margin: 20px 0;&quot;&gt;
        &lt;strong style=&quot;color: #059669;&quot;&gt;⭕ 緊急パッチ修正（After）: Null条件演算子（?.）とNull合体演算子（??）による安全フォールバック&lt;/strong&gt;
        &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14px; margin-top: 8px;&quot;&gt;
            &lt;span style=&quot;color: #93c5fd;&quot;&gt;public string&lt;/span&gt; &lt;span style=&quot;color: #67e8f9;&quot;&gt;GetUserPostalCode&lt;/span&gt;(&lt;span style=&quot;color: #93c5fd;&quot;&gt;User?&lt;/span&gt; user)&lt;br/&gt;
            {&lt;br/&gt;
            &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;// 連鎖的にnullをチェックし、どこかがnullなら安全なデフォルト値を返却&lt;/span&gt;&lt;br/&gt;
            &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #34d399; font-weight: bold;&quot;&gt;return user?.Profile?.Address?.PostalCode ?? &quot;未設定&quot;;&lt;/span&gt;&lt;br/&gt;
            }
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;緊急時こそ「再現テスト」を1本書いてからコミットせよ&lt;/h3&gt;
    &lt;p&gt;
        焦っているエンジニアが最もやってしまいがちなのが、「コードを一行直して、テストも動かさずに即ビルドして本番デプロイする」行為です。&lt;br/&gt;
        これは極めて危険です。焦った修正が別の副作用を生み、サービスがさらに致命的に壊れる二次災害を招きます。&lt;br/&gt;
        &lt;strong&gt;「障害を再現する単体テスト（Red）を書き、パッチ適用後にパスする（Green）ことを確認する」&lt;/strong&gt;——このわずか5分の手間で、二次災害を完全にシャットアウトできます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;// xUnitによる再現テストコード（障害ケースのカバー）&lt;/span&gt;&lt;br/&gt;
        [&lt;span style=&quot;color: #67e8f9;&quot;&gt;Fact&lt;/span&gt;]&lt;br/&gt;
        &lt;span style=&quot;color: #93c5fd;&quot;&gt;public void&lt;/span&gt; &lt;span style=&quot;color: #67e8f9;&quot;&gt;GetUserPostalCode_WhenProfileIsNull_ReturnsDefault&lt;/span&gt;()&lt;br/&gt;
        {&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #93c5fd;&quot;&gt;var&lt;/span&gt; user = &lt;span style=&quot;color: #93c5fd;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #67e8f9;&quot;&gt;User&lt;/span&gt; { Profile = &lt;span style=&quot;color: #93c5fd;&quot;&gt;null&lt;/span&gt; };&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #93c5fd;&quot;&gt;var&lt;/span&gt; service = &lt;span style=&quot;color: #93c5fd;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #67e8f9;&quot;&gt;UserService&lt;/span&gt;();&lt;br/&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #93c5fd;&quot;&gt;var&lt;/span&gt; result = service.GetUserPostalCode(user);&lt;br/&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #67e8f9;&quot;&gt;Assert&lt;/span&gt;.Equal(&lt;span style=&quot;color: #fde047;&quot;&gt;&quot;未設定&quot;&lt;/span&gt;, result); &lt;span style=&quot;color: #64748b;&quot;&gt;// クラッシュせずデフォルト値が返れば合格！&lt;/span&gt;&lt;br/&gt;
        }
    &lt;/div&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 10px 14px; border-radius: 4px; font-family: Consolas, monospace; font-size: 13.5px; margin-top: 8px;&quot;&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;dotnet&lt;/span&gt; test --filter FullyQualifiedName~GetUserPostalCode &lt;span style=&quot;color: #64748b;&quot;&gt;# テスト全件パスを確認！&lt;/span&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑤: developへのマージバック --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【図解】developへのマージバック：先祖返り（バグ復活）の完全防止&lt;/h2&gt;
    &lt;p&gt;
        本番にパッチを適用してサービスが正常稼働し、胸をなでおろした瞬間…実はここに&lt;strong&gt;「障害対応最大の落とし穴」&lt;/strong&gt;が潜んでいます。
    &lt;/p&gt;

    &lt;!-- 図解④ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1oc3DKeb3g7WrOb7XlpN-8OjFOb7aTczo&quot; alt=&quot;developへのマージバックと先祖返り防止&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】mainリリース反映後のdevelopへのマージバックと先祖返り（バグ復活）の完全防止&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        mainにマージして本番反映が完了しても、&lt;strong&gt;「developブランチ（次期開発本流）へのマージバック」&lt;/strong&gt;を行わなければ、障害対応は完了していません！&lt;br/&gt;
        もしマージバックを忘れた場合、次期バージョン（v1.1.0）のリリース時に、せっかく直したNullReferenceExceptionのバグが「復活（先祖返り）」してしまいます。ユーザーからは「あの会社、前に直したバグをまた出してるぞ…」と信頼を失墜させる原因になります。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #0f172a; margin-top: 30px; font-size: 19px;&quot;&gt;マージバックとブランチクリーンアップの手順&lt;/h3&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 14px 18px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 1. developブランチへ切り替えて最新化&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch develop&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; pull origin develop&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 2. hotfixの修正をdevelopへもマージバック&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; merge --no-ff hotfix/1.0.1 -m &lt;span style=&quot;color: #fde047;&quot;&gt;&quot;Merge hotfix/1.0.1 into develop (Prevent regression)&quot;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# （競合が発生した場合は、develop側の最新コードを活かしつつ修正を取り込んでコミット）&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 3. developの更新をプッシュ&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin develop&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 4. mainとdevelopの双方に統合されたことを確認し、hotfixブランチを削除&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; branch -d hotfix/1.0.1&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin --delete hotfix/1.0.1
    &lt;/div&gt;

    &lt;!-- セクション⑥: TortoiseGit / チートシート --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ TortoiseGitでの操作＆緊急対応5大チェックリスト&lt;/h2&gt;
    
    &lt;div style=&quot;background: #ffffff; border: 1px solid #cbd5e1; border-radius: 8px; padding: 20px; margin: 25px 0; box-shadow: 0 2px 4px rgba(0,0,0,0.03);&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 12px 0; color: #1e3a8a; font-size: 18px;&quot;&gt;🐢 TortoiseGitでの緊急ホットフィックス操作&lt;/h4&gt;
        &lt;ol style=&quot;margin: 0; padding-left: 22px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;hotfixブランチの作成:&lt;/strong&gt; 作業フォルダを右クリック → [TortoiseGit] → [ブランチの作成]。ブランチ名に &lt;code&gt;hotfix/1.0.1&lt;/code&gt; を入力し、基点（Base）に &lt;code&gt;main&lt;/code&gt;（またはタグ &lt;code&gt;v1.0.0&lt;/code&gt;）を選択。「新しいブランチをチェックアウト」にチェックしてOK。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;パッチ修正＆コミット:&lt;/strong&gt; C#コードを修正後、右クリック → [Git コミット]。最小限の差分のみ選択し、障害チケット番号を明記してコミット。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;mainへのマージ＆タグ打刻:&lt;/strong&gt; &lt;code&gt;main&lt;/code&gt; をチェックアウト後、右クリック → [マージ] で &lt;code&gt;hotfix/1.0.1&lt;/code&gt; を選択（「No Fast Forward」にチェック）。続いて右クリック → [タグの作成] で &lt;code&gt;v1.0.1&lt;/code&gt; を注釈付きで打刻。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;developへのマージバック:&lt;/strong&gt; &lt;code&gt;develop&lt;/code&gt; をチェックアウト後、同様に [マージ] で &lt;code&gt;hotfix/1.0.1&lt;/code&gt; を選択してマージ＆プッシュ。&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #fffbeb; border: 2px solid #f59e0b; border-radius: 8px; padding: 20px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 12px 0; color: #b45309; font-size: 18px;&quot;&gt;🛡️ 緊急ホットフィックス 5大チェックリスト&lt;/h4&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;☑️ &lt;strong&gt;main（最新本番）から分岐したか？&lt;/strong&gt; （誤ってdevelopから切っていないか）&lt;/li&gt;
            &lt;li&gt;☑️ &lt;strong&gt;関係ないコードの「ついで修正」を含めていないか？&lt;/strong&gt; （最小差分の原則）&lt;/li&gt;
            &lt;li&gt;☑️ &lt;strong&gt;障害再現の単体テストを書いてパスさせたか？&lt;/strong&gt; （二次災害防止）&lt;/li&gt;
            &lt;li&gt;☑️ &lt;strong&gt;mainにマージして注釈付きタグ（v1.0.1）を打ってプッシュしたか？&lt;/strong&gt;&lt;/li&gt;
            &lt;li&gt;☑️ &lt;strong&gt;developへもマージバックを完了させたか？&lt;/strong&gt; （先祖返りの完全遮断）&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- まとめセクション --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #3b82f6; border-radius: 10px; padding: 24px; margin: 40px 0;&quot;&gt;
        &lt;h3 style=&quot;margin: 0 0 15px 0; color: #1e3a8a; font-size: 21px;&quot;&gt;📌 本日のまとめと次回予告&lt;/h3&gt;
        &lt;p style=&quot;margin-bottom: 15px;&quot;&gt;
            本番障害時のホットフィックス対応は、エンジニアの技術力とチーム運用の成熟度が最も試される場面です。本日の重要原則を心に刻んでおきましょう。
        &lt;/p&gt;
        &lt;ul style=&quot;padding-left: 20px; line-height: 1.9;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;GitのHotfixは本番から完全隔離:&lt;/strong&gt; 未完成な開発中コードを一切混入させず、安全・迅速にパッチ適用が可能。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;修正範囲は「最小限」に限定:&lt;/strong&gt; 焦った時のリファクタリングや余計な変更は二次災害の元。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;緊急時こそ単体テスト（dotnet test）を必ず書く:&lt;/strong&gt; 再現テストを通す5分がサービスの命運を分ける。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;developへのマージバックを絶対に忘れない:&lt;/strong&gt; 両系統への反映を確認して初めてホットフィックスは完了する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;完了後はhotfixブランチを削除:&lt;/strong&gt; 役目を終えたブランチは速やかに片付け、リポジトリを整理整頓。&lt;/li&gt;
        &lt;/ul&gt;
        &lt;div style=&quot;background: #eff6ff; padding: 14px 18px; border-radius: 6px; margin-top: 15px;&quot;&gt;
            &lt;strong style=&quot;color: #1d4ed8;&quot;&gt;次回予告【Day 25】: 【Case 5】仕様変更・機能のリリース順序入れ替え（チェリーピック）&lt;/strong&gt;&lt;br/&gt;
            「機能Aはリリース延期になったが、一緒に開発していた機能Bだけを先行リリースしたい！」という現場からの急なリクエスト。Gitの &lt;code&gt;cherry-pick&lt;/code&gt; を駆使して、特定コミットだけを安全に摘み食いしてリリースへ移植するプロフェッショナルの現場技を徹底解説します！
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/4350464692634907152/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-24case-4-hotfix.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4350464692634907152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/4350464692634907152'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-24case-4-hotfix.html' title='【Day 24】【Case 4】本番障害！ 緊急バグ修正（Hotfix）の完全手順'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/16vf0iT-raXrUO3xpFKKhX8wJ5QbnBQ47=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-7810364101672077611</id><published>2026-10-22T09:22:08.276+09:00</published><updated>2026-10-22T09:22:08.276+09:00</updated><title type='text'>【Day 26】docker compose up / down / build の実務コマンド完全マスター 〜バックグラウンド起動（-d）、差分再ビルド（--build）、ログ監視、コンテナ・ボリューム完全初期化（down -v）の実務頻出ワークフローとC#開発サイクル〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1_nBbdZG1sJaRV8vZj_LaN46DvELaJ8DN&quot; alt=&quot;Day 26 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 26: docker compose up / down / build の実務コマンド完全マスター&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 導入メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: linear-gradient(135deg, #e0f2fe 0%, #f0fdf4 100%); border-left: 6px solid #0db7ed; border-radius: 8px; padding: 22px 24px; margin: 30px 0; box-shadow: 0 4px 12px rgba(13,183,237,0.08);&quot;&gt;
        &lt;div style=&quot;font-size: 32px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;font-size: 15.5px; color: #0f172a;&quot;&gt;
            &lt;p style=&quot;margin: 0 0 10px 0; font-weight: bold; color: #0369a1; font-size: 17px;&quot;&gt;「C#コードを直したのにコンテナに反映されない…」「DBを初期状態にやり直したい…」と悩んでいませんか？&lt;/p&gt;
            &lt;p style=&quot;margin: 0; line-height: 1.8;&quot;&gt;
                Windows ServerやIIS、物理サーバーで長年システム構築・運用に携わってきたベテランエンジニアにとって、「サービスの再起動」や「設定反映」「テストデータ初期化」は、GUIツールや手動バッチで行うのが日常茶飯事でした。&lt;br/&gt;
                しかしDocker Composeを導入すると、&lt;strong&gt;「&lt;code&gt;docker compose up&lt;/code&gt; を叩いても古いイメージのまま起動する」「ターミナルがログ出力で埋まって次の操作ができない」「コンテナを消したのに前回の古いDBデータがゾンビのように残っている」&lt;/strong&gt;という独特の挙動に戸惑う方が続出します。&lt;br/&gt;
                本講義では、実務の現場で毎日何十回と叩くことになる &lt;strong&gt;&lt;code&gt;up&lt;/code&gt; / &lt;code&gt;down&lt;/code&gt; / &lt;code&gt;build&lt;/code&gt; / &lt;code&gt;ps&lt;/code&gt; / &lt;code&gt;logs&lt;/code&gt; の黄金オプションとライフサイクル&lt;/strong&gt; を徹底解説し、C#/.NET開発における超高速でクリーンな開発サイクルを確立します！
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 目次セクション --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 24px; margin: 30px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 12px; font-size: 17px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 4px; padding: 2px 8px; font-size: 13px; margin-right: 10px;&quot;&gt;INDEX&lt;/span&gt;
            本日の講義カリキュラム
        &lt;/h3&gt;
        &lt;ol style=&quot;margin: 0; padding-left: 22px; color: #334155; line-height: 2;&quot;&gt;
            &lt;li&gt;&lt;a href=&quot;#sec1&quot; style=&quot;color: #0284c7; text-decoration: none; font-weight: 500;&quot;&gt;最速・確実な起動コマンド: &lt;code&gt;docker compose up -d --build&lt;/code&gt; の全貌&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;#sec2&quot; style=&quot;color: #0284c7; text-decoration: none; font-weight: 500;&quot;&gt;データの運命を分ける停止コマンド: &lt;code&gt;down&lt;/code&gt; vs &lt;code&gt;down -v&lt;/code&gt; の決定的な違い&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;#sec3&quot; style=&quot;color: #0284c7; text-decoration: none; font-weight: 500;&quot;&gt;状態監視とトラブルシューティング: &lt;code&gt;docker compose ps&lt;/code&gt; と &lt;code&gt;logs -f&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;#sec4&quot; style=&quot;color: #0284c7; text-decoration: none; font-weight: 500;&quot;&gt;Gitブランチ運用と連動するC#現場の最短開発ワークフロー&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;#sec5&quot; style=&quot;color: #0284c7; text-decoration: none; font-weight: 500;&quot;&gt;実務頻出 Compose CLI クイックリファレンス早見表&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;#sec6&quot; style=&quot;color: #0284c7; text-decoration: none; font-weight: 500;&quot;&gt;本日のまとめと理解度チェック&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;!-- セクション1 --&gt;
    &lt;h2 id=&quot;sec1&quot; style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 最速・確実な起動コマンド: &lt;code&gt;docker compose up -d --build&lt;/code&gt; の全貌&lt;/h2&gt;
    &lt;p&gt;
        Docker Compose環境で日々の開発を始めるとき、あるいはソースコードを修正したとき、最も頻繁に叩く基本コマンドが &lt;code&gt;docker compose up&lt;/code&gt; です。&lt;br/&gt;
        しかし、オプションを指定せずに単に &lt;code&gt;docker compose up&lt;/code&gt; と実行すると、開発現場では以下の2大問題が確実に発生します。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1yd7PDAHAn8HeQoa2ccf_99UnMMGicc9_&quot; alt=&quot;起動と再ビルドの仕組み&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】docker compose up -d --build の3ステップ差分再ビルド＆バックグラウンド起動フロー&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;background: #fff1f2; border: 1px solid #fecdd3; border-radius: 6px; padding: 18px 20px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;color: #be123c; margin-top: 0; margin-bottom: 8px; font-size: 16px;&quot;&gt;⚠️ 単純な &lt;code&gt;docker compose up&lt;/code&gt; の2大落とし穴&lt;/h4&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #9f1239; font-size: 14.5px; line-height: 1.8;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;落とし穴1（ターミナル占有）:&lt;/strong&gt; デフォルトではフォアグラウンド実行となり、全コンテナのログがターミナル画面を埋め尽くします。コンソールがロックされ、次のコマンド入力ができなくなってしまいます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;落とし穴2（古いイメージの再利用）:&lt;/strong&gt; Composeは「既にローカルにビルド済みイメージが存在する場合、Dockerfileの変更がない限り再ビルドをスキップする」という最適化を行います。そのため、C#の &lt;code&gt;.cs&lt;/code&gt; コードを変更しても古いバイナリのままコンテナが起動してしまいます。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;p&gt;
        この2つの問題を一撃で解決するのが、&lt;strong&gt;&lt;code&gt;-d&lt;/code&gt;（デタッチ）&lt;/strong&gt; と &lt;strong&gt;&lt;code&gt;--build&lt;/code&gt;（再ビルド強制）&lt;/strong&gt; の組み合わせです。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; border-radius: 8px; padding: 18px 22px; margin: 25px 0; color: #f8fafc; font-family: Consolas, monospace; font-size: 15px; box-shadow: 0 4px 14px rgba(0,0,0,0.15);&quot;&gt;
        &lt;div style=&quot;color: #64748b; font-size: 12px; margin-bottom: 8px; border-bottom: 1px solid #334155; padding-bottom: 4px;&quot;&gt;# 実務で毎日10回以上叩く鉄板コマンド&lt;/div&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose&lt;/span&gt; up -d --build
    &lt;/div&gt;

    &lt;p&gt;
        このコマンドを実行すると、Composeは以下の3ステップを自動で高速実行します：
    &lt;/p&gt;
    &lt;ol style=&quot;padding-left: 24px; line-height: 1.9;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;① ソースコードの差分検知:&lt;/strong&gt; Dockerfileやコンテキスト内のC#ファイルに変更があるサービスのみを識別します。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;② 差分再ビルド（&lt;code&gt;--build&lt;/code&gt;）:&lt;/strong&gt; 変更のあったコンテナイメージのみをDockerキャッシュを活用して数秒でリビルドします（変更のないSQL ServerやRedisはビルドをスキップ）。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;③ バックグラウンド起動（&lt;code&gt;-d&lt;/code&gt;）:&lt;/strong&gt; コンテナをバックグラウンド（デーモン）プロセスとして立ち上げ、ターミナルの制御を即座にユーザーへ返却します。&lt;/li&gt;
    &lt;/ol&gt;

    &lt;!-- セクション2 --&gt;
    &lt;h2 id=&quot;sec2&quot; style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② データの運命を分ける停止コマンド: &lt;code&gt;down&lt;/code&gt; vs &lt;code&gt;down -v&lt;/code&gt; の決定的な違い&lt;/h2&gt;
    &lt;p&gt;
        コンテナの運用を終了するとき、あるいは環境をリセットしたいときに使うのが &lt;code&gt;docker compose down&lt;/code&gt; です。&lt;br/&gt;
        ここで絶対に押さえておくべきが、&lt;strong&gt;「&lt;code&gt;down&lt;/code&gt; 単体」&lt;/strong&gt; と &lt;strong&gt;「&lt;code&gt;down -v&lt;/code&gt;」&lt;/strong&gt; の決定的な動作の違いです。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1UNnJNz36pg6aG4fS6TUmDGs9up7jmB-Z&quot; alt=&quot;down と down -v の違い&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】通常の停止（down） vs ボリューム完全初期化（down -v）の決定的な違いと用途&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        両者の違いを表形式で明確に整理しておきましょう。
    &lt;/p&gt;

    &lt;div style=&quot;overflow-x: auto; margin: 25px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15px; background: #ffffff; border: 1px solid #cbd5e1; border-radius: 8px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #f1f5f9; color: #0f172a; border-bottom: 2px solid #cbd5e1; text-align: left;&quot;&gt;
                    &lt;th style=&quot;padding: 12px 16px;&quot;&gt;比較項目&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 16px; color: #0284c7;&quot;&gt;&lt;code&gt;docker compose down&lt;/code&gt;（通常）&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 16px; color: #ea580c;&quot;&gt;&lt;code&gt;docker compose down -v&lt;/code&gt;（ボリューム破棄）&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 16px; font-weight: bold;&quot;&gt;コンテナとネットワーク&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; color: #166534;&quot;&gt;安全に停止して削除&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; color: #166534;&quot;&gt;安全に停止して削除&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0; background: #fafafa;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 16px; font-weight: bold;&quot;&gt;データベースのデータ（Volume）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; color: #0369a1; font-weight: bold;&quot;&gt;保持される（データ消えない）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; color: #dc2626; font-weight: bold;&quot;&gt;完全に消去される（初期化）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 16px; font-weight: bold;&quot;&gt;主な利用シーン&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px;&quot;&gt;一日の作業終了、PCの再起動前&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px;&quot;&gt;EF Coreマイグレーションのやり直し、Gitブランチ切替時&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 12px 16px; font-weight: bold;&quot;&gt;オンプレミス換算の作業&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px;&quot;&gt;サービスの停止・開始&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px;&quot;&gt;DROP DATABASE ＋ CREATE DATABASE ＋ 初期データ投入&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 6px; padding: 18px 20px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;color: #15803d; margin-top: 0; margin-bottom: 8px; font-size: 16px;&quot;&gt;💡 C# Entity Framework Core 開発での絶大な威力&lt;/h4&gt;
        &lt;p style=&quot;margin: 0; color: #166534; font-size: 14.5px; line-height: 1.8;&quot;&gt;
            チーム開発で別ブランチから最新コードをプルした際、データベースのスキーマとC#モデルクラスの定義が食い違ってマイグレーション例外（&lt;code&gt;SqlException&lt;/code&gt;）が発生することがあります。&lt;br/&gt;
            そんな時は迷わず &lt;strong&gt;&lt;code&gt;docker compose down -v&lt;/code&gt; ➡ &lt;code&gt;docker compose up -d&lt;/code&gt;&lt;/strong&gt; を実行してください。&lt;br/&gt;
            壊れたスキーマが瞬時に消滅し、クリーンなSQL Serverがわずか数秒で再構築されます。オンプレ時代のようにSQL Server Management Studio（SSMS）を開いてテーブルを手動DROPする手間は完全にゼロになります！
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- セクション3 --&gt;
    &lt;h2 id=&quot;sec3&quot; style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 状態監視とトラブルシューティング: &lt;code&gt;docker compose ps&lt;/code&gt; と &lt;code&gt;logs -f&lt;/code&gt;&lt;/h2&gt;
    &lt;p&gt;
        バックグラウンド（&lt;code&gt;-d&lt;/code&gt;）で立ち上げた複数コンテナが「本当に元気に動いているのか？」を確認し、トラブル発生時に原因を特定するための2大監視コマンドをマスターしましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1jP5a6zdkivQFTrz7RTaSbXs4ejumoEai&quot; alt=&quot;状態確認とトラブルシューティング&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】docker compose ps（死活監視）と logs -f（リアルタイムログ監視）のトラブルシューティング&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; font-size: 19px; margin-top: 30px; margin-bottom: 14px;&quot;&gt;1. コンテナの健康診断: &lt;code&gt;docker compose ps&lt;/code&gt;&lt;/h3&gt;
    &lt;p&gt;
        &lt;code&gt;docker compose ps&lt;/code&gt; を実行すると、YAMLファイルで定義されたすべてのサービスの状態が一括表示されます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; border-radius: 8px; padding: 18px 22px; margin: 20px 0; color: #f8fafc; font-family: Consolas, monospace; font-size: 14px; overflow-x: auto;&quot;&gt;
&lt;span style=&quot;color: #64748b;&quot;&gt;$ docker compose ps&lt;/span&gt;
NAME                IMAGE               COMMAND                  SERVICE             STATUS                    PORTS
docker-webapi-1     docker-webapi       &quot;dotnet DockerApi.dll&quot;   webapi              Up 2 minutes              0.0.0.0:5000-&gt;8080/tcp
docker-sqlserver-1  mcr.microsoft.com   &quot;/opt/mssql/bin/sqls…&quot;   sqlserver           Up 2 minutes (healthy)    0.0.0.0:1433-&gt;1433/tcp
docker-redis-1      redis:7-alpine      &quot;docker-entrypoint.s…&quot;   redis               Up 2 minutes (healthy)    0.0.0.0:6379-&gt;6379/tcp
    &lt;/div&gt;

    &lt;p&gt;
        注目すべきは &lt;strong&gt;&lt;code&gt;STATUS&lt;/code&gt; 列&lt;/strong&gt; です。&lt;code&gt;Up&lt;/code&gt; と表示されていれば正常稼働中、前回設定した &lt;code&gt;healthcheck&lt;/code&gt; が成功していれば &lt;code&gt;(healthy)&lt;/code&gt; と表示されます。&lt;br/&gt;
        もし設定ミスや例外で起動に失敗しているコンテナがあれば、&lt;code&gt;Exit 1&lt;/code&gt; や &lt;code&gt;restarting&lt;/code&gt; と表示され、異常が一瞬で判明します。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #0f172a; font-size: 19px; margin-top: 35px; margin-bottom: 14px;&quot;&gt;2. リアルタイムログ追跡: &lt;code&gt;docker compose logs -f&lt;/code&gt;&lt;/h3&gt;
    &lt;p&gt;
        「Web APIが起動しない」「500 Internal Server Errorが発生した」という場合は、&lt;code&gt;logs&lt;/code&gt; コマンドで出力を確認します。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; border-radius: 8px; padding: 18px 22px; margin: 20px 0; color: #f8fafc; font-family: Consolas, monospace; font-size: 14px;&quot;&gt;
        &lt;div style=&quot;color: #64748b; font-size: 12px; margin-bottom: 8px; border-bottom: 1px solid #334155; padding-bottom: 4px;&quot;&gt;# 全コンテナのログを色分けしてリアルタイム監視（Ctrl+Cで終了）&lt;/div&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose&lt;/span&gt; logs -f&lt;br/&gt;&lt;br/&gt;
        &lt;div style=&quot;color: #64748b; font-size: 12px; margin-bottom: 8px; border-bottom: 1px solid #334155; padding-bottom: 4px;&quot;&gt;# Web APIコンテナだけに絞り込み、直近50行からストリーム追跡&lt;/div&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose&lt;/span&gt; logs -f --tail=50 webapi
    &lt;/div&gt;

    &lt;p&gt;
        &lt;code&gt;-f&lt;/code&gt;（follow）オプションを付けることで、Linuxの &lt;code&gt;tail -f&lt;/code&gt; と同様に新規出力されるログをリアルタイムで追跡できます。&lt;br/&gt;
        さらにサービス名（&lt;code&gt;webapi&lt;/code&gt; など）を指定すれば、SQL Serverなどの余計なログを排除して、C#アプリケーションの例外スタックトレースだけを集中して監視できます。
    &lt;/p&gt;

    &lt;!-- セクション4 --&gt;
    &lt;h2 id=&quot;sec4&quot; style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ Gitブランチ運用と連動するC#現場の最短開発ワークフロー&lt;/h2&gt;
    &lt;p&gt;
        Composeコマンドを単体で知っていても、実際のチーム開発フローに組み込めなければ意味がありません。&lt;br/&gt;
        C#実務の現場でブランチを切り替えて機能開発を進める際の、&lt;strong&gt;「事故ゼロ・最短黄金サイクル」&lt;/strong&gt; を図解と手順でマスターしましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/12FtGiEE4TF_Txor3B0P4M30AZQGqg8TU&quot; alt=&quot;C#現場の開発サイクル&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】Gitブランチ切り替えからコンテナ反映・マイグレーション適用までのC#現場最短ワークフロー&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0f172a; font-size: 19px; margin-top: 30px; margin-bottom: 14px;&quot;&gt;プロが実践する3大シチュエーション別コマンド集&lt;/h3&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 22px; margin: 20px 0;&quot;&gt;
        &lt;h4 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 10px; font-size: 16px;&quot;&gt;シナリオA: Gitブランチを切り替えて別機能のレビューを行うとき&lt;/h4&gt;
        &lt;div style=&quot;background: #0f172a; border-radius: 6px; padding: 14px 18px; color: #f8fafc; font-family: Consolas, monospace; font-size: 13.5px; margin: 10px 0;&quot;&gt;
            &lt;span style=&quot;color: #64748b;&quot;&gt;# 1. 前のブランチのコンテナとDBボリュームを完全破棄&lt;/span&gt;&lt;br/&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose&lt;/span&gt; down -v&lt;br/&gt;&lt;br/&gt;
            &lt;span style=&quot;color: #64748b;&quot;&gt;# 2. 対象ブランチにスイッチ＆最新コード取得&lt;/span&gt;&lt;br/&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch feature/order-api&lt;br/&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; pull origin feature/order-api&lt;br/&gt;&lt;br/&gt;
            &lt;span style=&quot;color: #64748b;&quot;&gt;# 3. 新ブランチのコードで差分ビルド＆起動&lt;/span&gt;&lt;br/&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose&lt;/span&gt; up -d --build
        &lt;/div&gt;
        &lt;p style=&quot;margin: 0; font-size: 14px; color: #475569;&quot;&gt;
            💡 &lt;strong&gt;ポイント:&lt;/strong&gt; ブランチ切り替え前に &lt;code&gt;down -v&lt;/code&gt; を実行することで、古いブランチで適用されたDBマイグレーションの残骸が新ブランチに悪影響を及ぼす事故を100%防止できます。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 22px; margin: 20px 0;&quot;&gt;
        &lt;h4 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 10px; font-size: 16px;&quot;&gt;シナリオB: C#コード（ControllersやServices）を編集した直後の動作確認&lt;/h4&gt;
        &lt;div style=&quot;background: #0f172a; border-radius: 6px; padding: 14px 18px; color: #f8fafc; font-family: Consolas, monospace; font-size: 13.5px; margin: 10px 0;&quot;&gt;
            &lt;span style=&quot;color: #64748b;&quot;&gt;# C#コードを保存したら、この1コマンドを叩くだけ！&lt;/span&gt;&lt;br/&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose&lt;/span&gt; up -d --build webapi
        &lt;/div&gt;
        &lt;p style=&quot;margin: 0; font-size: 14px; color: #475569;&quot;&gt;
            💡 &lt;strong&gt;ポイント:&lt;/strong&gt; 末尾に &lt;code&gt;webapi&lt;/code&gt; とサービス名を指定することで、SQL ServerやRedisを一切触らず、Web APIコンテナだけをピンポイントで最速再ビルド＆再起動できます。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 22px; margin: 20px 0;&quot;&gt;
        &lt;h4 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 10px; font-size: 16px;&quot;&gt;シナリオC: 設定ファイル（appsettings.Development.json）だけを変更したとき&lt;/h4&gt;
        &lt;div style=&quot;background: #0f172a; border-radius: 6px; padding: 14px 18px; color: #f8fafc; font-family: Consolas, monospace; font-size: 13.5px; margin: 10px 0;&quot;&gt;
            &lt;span style=&quot;color: #64748b;&quot;&gt;# 再ビルド不要！わずか1秒でプロセスだけ再起動&lt;/span&gt;&lt;br/&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose&lt;/span&gt; restart webapi
        &lt;/div&gt;
        &lt;p style=&quot;margin: 0; font-size: 14px; color: #475569;&quot;&gt;
            💡 &lt;strong&gt;ポイント:&lt;/strong&gt; ホスト側のボリュームマウント（Bind Mount）で設定を渡している場合、再ビルドは不要です。&lt;code&gt;restart&lt;/code&gt; コマンドでプロセスのみを再起動すれば即座に新設定がロードされます。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- セクション5 --&gt;
    &lt;h2 id=&quot;sec5&quot; style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 実務頻出 Compose CLI クイックリファレンス早見表&lt;/h2&gt;
    &lt;p&gt;
        日常の開発でデスクトップに貼っておきたい「Compose実務コマンド一覧表」です。迷ったときはこの表を参照してください。
    &lt;/p&gt;

    &lt;div style=&quot;overflow-x: auto; margin: 25px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 14.5px; background: #ffffff; border: 1px solid #cbd5e1; border-radius: 8px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #0f172a; color: #f8fafc;&quot;&gt;
                    &lt;th style=&quot;padding: 12px 14px; text-align: left; width: 38%;&quot;&gt;コマンド&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 14px; text-align: left; width: 38%;&quot;&gt;動作と効果&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 14px; text-align: left; width: 24%;&quot;&gt;頻度&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0; background: #f0fdf4;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; font-family: Consolas, monospace; font-weight: bold; color: #0284c7;&quot;&gt;docker compose up -d --build&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px;&quot;&gt;差分を再ビルドし、バックグラウンドで全サービス起動&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; color: #166534; font-weight: bold;&quot;&gt;★★★★★（最頻出）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; font-family: Consolas, monospace; color: #334155;&quot;&gt;docker compose down&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px;&quot;&gt;コンテナ・ネットワークを停止・削除（DBデータは保持）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; color: #0284c7;&quot;&gt;★★★★☆&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0; background: #fff7ed;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; font-family: Consolas, monospace; font-weight: bold; color: #ea580c;&quot;&gt;docker compose down -v&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px;&quot;&gt;コンテナに加え、DBボリュームも完全削除（完全初期化）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; color: #ea580c; font-weight: bold;&quot;&gt;★★★★☆&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; font-family: Consolas, monospace; color: #334155;&quot;&gt;docker compose ps&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px;&quot;&gt;稼働中コンテナの一覧、ヘルスチェック状態、ポート表示&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; color: #0284c7;&quot;&gt;★★★★☆&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0; background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; font-family: Consolas, monospace; color: #334155;&quot;&gt;docker compose logs -f [srv]&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px;&quot;&gt;リアルタイムで標準出力ログを監視（サービス絞り込み可）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; color: #166534;&quot;&gt;★★★★★&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;border-bottom: 1px solid #e2e8f0;&quot;&gt;
                    &lt;td style=&quot;padding: 10px 14px; font-family: Consolas, monospace; color: #334155;&quot;&gt;docker compose restart [srv]&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px;&quot;&gt;指定したコンテナのみを再ビルドなしで即座に再起動&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; color: #64748b;&quot;&gt;★★★☆☆&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px 14px; font-family: Consolas, monospace; color: #334155;&quot;&gt;docker compose exec [srv] [cmd]&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px;&quot;&gt;稼働中コンテナ内でコマンド実行（例: &lt;code&gt;dotnet ef ...&lt;/code&gt;）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 14px; color: #64748b;&quot;&gt;★★★☆☆&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- セクション6 --&gt;
    &lt;h2 id=&quot;sec6&quot; style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ 本日のまとめと理解度チェック&lt;/h2&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #cbd5e1; border-radius: 8px; padding: 22px 24px; margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 14px; font-size: 18px;&quot;&gt;💡 本日の重要ポイント総まとめ&lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #334155; line-height: 1.9;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;起動の標準形（&lt;code&gt;up -d --build&lt;/code&gt;）:&lt;/strong&gt; ターミナルを解放する &lt;code&gt;-d&lt;/code&gt; と、コード差分を確実に反映する &lt;code&gt;--build&lt;/code&gt; をセットで運用する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;データの保持と破棄（&lt;code&gt;down&lt;/code&gt; vs &lt;code&gt;down -v&lt;/code&gt;）:&lt;/strong&gt; PC終了時は通常の &lt;code&gt;down&lt;/code&gt; でデータを保護し、マイグレーション不整合やブランチ切替時は &lt;code&gt;down -v&lt;/code&gt; でボリュームごとクリーンリセットする。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;状態監視（&lt;code&gt;ps&lt;/code&gt; と &lt;code&gt;logs -f&lt;/code&gt;）:&lt;/strong&gt; 異常終了は &lt;code&gt;ps&lt;/code&gt; で即座にあぶり出し、例外スタックトレースは &lt;code&gt;logs -f [サービス名]&lt;/code&gt; でリアルタイム追跡する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;C#開発の黄金ループ:&lt;/strong&gt; 「Gitブランチ切替 ➡ &lt;code&gt;down -v&lt;/code&gt; で初期化 ➡ &lt;code&gt;up -d --build&lt;/code&gt; 起動」により、オンプレミス時代の手動DB管理から完全に解放される。&lt;/li&gt;
        &lt;/ul&gt;
        &lt;div style=&quot;margin-top: 15px; padding-top: 12px; border-top: 1px dashed #86efac; font-size: 15px; color: #14532d;&quot;&gt;
            &lt;strong&gt;次回【Day 27】予告:&lt;/strong&gt;&lt;br/&gt;
            第6部 データ永続化編突入！『コンテナを破棄するとデータが消える！？ データの永続化の原理（Volume &amp; Bind Mount）』〜UnionFS/OverlayFSの書き込みレイヤーの仕組みと、ホストOS側にデータを逃がすボリューム設計を完全図解〜
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/7810364101672077611/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-26docker-compose-up-down-build-d.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/7810364101672077611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/7810364101672077611'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-26docker-compose-up-down-build-d.html' title='【Day 26】docker compose up / down / build の実務コマンド完全マスター 〜バックグラウンド起動（-d）、差分再ビルド（--build）、ログ監視、コンテナ・ボリューム完全初期化（down -v）の実務頻出ワークフローとC#開発サイクル〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1_nBbdZG1sJaRV8vZj_LaN46DvELaJ8DN=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-3281009115311701485</id><published>2026-10-21T18:11:12.803+09:00</published><updated>2026-10-21T18:11:12.803+09:00</updated><title type='text'>【Day 23】【Case 3】本番リリースとタグ打ち（安定バージョンの凍結）</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1F5w3ybkmcLPsUICLtBJZEIbDS5teDSte&quot; alt=&quot;Day 23 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 23】本番リリースとタグ打ち（安定バージョンの凍結）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 22では、リリースブランチ（&lt;code&gt;release/v1.0.0&lt;/code&gt;）を活用して、次期新機能開発をブロックせずにステージング検証とバグ修正だけを綺麗に収束させる手法を学びました。&lt;br/&gt;
            本日のDay 23は、第5部 ケーススタディの第3弾として、開発サイクルの集大成である&lt;strong&gt;【本番リリースとタグ打ち（安定バージョンの凍結）】&lt;/strong&gt;を徹底解説します！&lt;br/&gt;
            Subversion (SVN) や Visual SourceSafe (VSS) で長年開発されてきたベテランエンジニアの方なら、「リリース時に tags フォルダへ丸ごとコピーしたけれど、後から誰かが tags 配下のファイルを直接編集・コミットしてしまい、リリース時と実際のバイナリが一致しなくなった」「リビジョン番号が大きすぎてどのコミットが製品版かわからない」といった苦いトラブルを経験したことがあるはずです。&lt;br/&gt;
            Gitのタグ機能は、特定コミットに対する&lt;strong&gt;「暗号学的に改ざん不可能な不変のピン留め」&lt;/strong&gt;です。特に「注釈付きタグ（Annotated Tag）」を使えば、リリース担当者の署名・日時・リリースノートがリポジトリ内に永久に記録され、いつでも寸分の狂いもなく過去のリリース状態を100%再現できます。&lt;br/&gt;
            本日は、検証完了後の安全なmainマージ手順、セマンティックバージョニング（v1.0.0）に基づくタグ打ち、C#のアセンブリバージョン（&lt;code&gt;Directory.Build.props&lt;/code&gt;）とGitHub Releasesの自動公開連携、そしてリリース直後に絶対に忘れてはならない&lt;strong&gt;「developへのマージバック（先祖返り完全防止）」&lt;/strong&gt;まで、現場で即座に役立つ実践ノウハウを完全網羅してお届けします！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        結合テストやステージング環境でのQA検証が無事に完了すると、いよいよ製品をエンドユーザーに届ける「本番リリース」を迎えます。&lt;br/&gt;
        この最終段階で最も求められるのは、&lt;strong&gt;「リリースしたコードが絶対に改ざんされず、1年後でも10年後でも寸分違わず同一のビルドを再現できる確実性」&lt;/strong&gt;です。&lt;br/&gt;
        Gitのタグ（Tag）とブランチ統合の完全サイクルをマスターすることで、人為的ミスやデグレ（退行バグ）を極限まで排除したプロフェッショナルなリリース体制を構築できます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;SVNの「タグフォルダコピー（重い・変更可能）」とGitの「コミットへの不変タグ打刻」の本質的違いを腹落ちさせる&lt;/li&gt;
            &lt;li&gt;リリースブランチからmainブランチへの安全なマージ作法（&lt;code&gt;git merge --no-ff&lt;/code&gt;）を習得する&lt;/li&gt;
            &lt;li&gt;「軽量タグ（Lightweight）」と「注釈付きタグ（Annotated）」の違いを理解し、本番リリースには必ず注釈付きタグ（&lt;code&gt;-a&lt;/code&gt;）を使う原則を徹底する&lt;/li&gt;
            &lt;li&gt;C# / .NET プロジェクトにおけるバージョン一括管理（&lt;code&gt;Directory.Build.props&lt;/code&gt;）とGitHub Releases自動公開の連携フローを理解する&lt;/li&gt;
            &lt;li&gt;mainリリース完了後にバグ修正をdevelopへマージバックし、先祖返り（バグ復活）を100%防止するサイクルを完結させる&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: SVNタグコピー vs Gitタグ打刻 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】SVNのタグコピー vs Gitのタグ打刻：なぜGitのタグは「完全不変」なのか？&lt;/h2&gt;
    &lt;p&gt;
        まずは、SVNなどの集中型バージョン管理とGitにおける「タグ（Tag）」の決定的な設計思想の違いを確認しましょう。
    &lt;/p&gt;

    &lt;!-- 図解①: SVN vs Git タグ対比 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1sUH1Y_HtGXg7aJzSDVpf8irN9J5Jz5pk&quot; alt=&quot;SVNタグコピー vs Gitタグ打刻&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】SVNの「フォルダ複製（重い・変更可能）」vs Gitの「不変ピン留め（軽量・改ざん不可）」&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        SVNにおけるタグは、技術的には「&lt;code&gt;/trunk&lt;/code&gt; または &lt;code&gt;/branches&lt;/code&gt; のディレクトリを &lt;code&gt;/tags/v1.0.0/&lt;/code&gt; へ丸ごとコピー（svn copy）したもの」に過ぎません。&lt;br/&gt;
        そのため、運用ルールで「tags配下は変更禁止」と決めていても、うっかり誰かが &lt;code&gt;/tags/v1.0.0/&lt;/code&gt; 内のソースコードを編集してコミットできてしまう重大な脆弱性がありました。&lt;br/&gt;
        その結果、「本番環境で動いているプログラムと、tagsフォルダのコードが微妙に違う！」という致命的なトラブルが現場で後を絶たなかったのです。
    &lt;/p&gt;
    &lt;p&gt;
        対照的に、Gitのタグは&lt;strong&gt;「特定コミットオブジェクトのSHA-1/SHA-256ハッシュ値を指す、不変の参照ポインタ」&lt;/strong&gt;です。&lt;br/&gt;
        Gitのコミット履歴は暗号学的なハッシュチェーンで保護されているため、コミット内容や親コミットを1ビットでも書き換えるとハッシュ値が変わります。したがって、タグが指すコードの内容を後から改ざんすることは不可能です。&lt;br/&gt;
        さらに、実体は数十バイトの参照情報にすぎないため、作成は一瞬（0秒）であり、リポジトリの容量を圧迫することも一切ありません。
    &lt;/p&gt;

    &lt;div style=&quot;background: #ffffff; border: 1px solid #cbd5e1; border-radius: 8px; padding: 20px; margin: 24px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 12px 0; color: #0f172a; font-size: 17px;&quot;&gt;📊 SVNタグとGitタグの徹底対比表&lt;/h4&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #f1f5f9; text-align: left;&quot;&gt;
                    &lt;th style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1;&quot;&gt;比較項目&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1;&quot;&gt;SVNのタグ（svn copy）&lt;/th&gt;
                    &lt;th style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1;&quot;&gt;Gitのタグ（git tag）&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;仕組み・実体&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1;&quot;&gt;別フォルダへの丸ごと複製&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;特定コミットへの不変ポインタ（0バイト級）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;改ざん耐性・不変性&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1; color: #dc2626;&quot;&gt;後から編集・コミット可能（危険）&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;暗号学的ハッシュで完全保護（改ざん不能）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;作成速度・負荷&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1;&quot;&gt;サーバー通信とコピー処理が必要&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;ミリ秒単位で瞬時に完了&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;メタデータ記録&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1;&quot;&gt;SVNコミットログのみ&lt;/td&gt;
                    &lt;td style=&quot;padding: 10px 12px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;作成者、作成日時、GPG署名、詳細メッセージ&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- セクション③: mainマージと注釈付きタグ打刻の実践手順 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】mainマージと注釈付きタグ打刻（Annotated Tag）の実践手順&lt;/h2&gt;
    &lt;p&gt;
        ステージング環境でのQAテストが合格したら、リリースブランチを本番リリース用ブランチ（&lt;code&gt;main&lt;/code&gt;）へと統合し、バージョンタグを打刻します。
    &lt;/p&gt;

    &lt;!-- 図解②: mainマージと注釈付きタグフロー --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1B2IiGJL8bZFqlmhT2Gyz3e_4hCvlo-qi&quot; alt=&quot;mainマージと注釈付きタグ打刻フロー&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】リリース完了からmainマージ、注釈付きタグ（Annotated Tag）打刻までの3ステップ&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 25px;&quot;&gt;1. なぜ「軽量タグ」ではなく「注釈付きタグ」を使うのか？&lt;/h3&gt;
    &lt;p&gt;
        Gitのタグには2種類が存在します。
    &lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;軽量タグ（Lightweight Tag）:&lt;/strong&gt; &lt;code&gt;git tag v1.0.0&lt;/code&gt; のようにオプションなしで作成。単なるコミットへの別名（エイリアス）であり、作成者や日時のメタデータは一切保持されません。個人開発の一時的なブックマーク用です。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;注釈付きタグ（Annotated Tag）:&lt;/strong&gt; &lt;code&gt;git tag -a v1.0.0 -m &quot;メッセージ&quot;&lt;/code&gt; で作成。Git内部で独立した「タグオブジェクト」として保存され、&lt;strong&gt;作成者の名前・メールアドレス・作成日時・リリースノートメッセージ・（任意で）GPG電子署名&lt;/strong&gt;が強固に記録されます。&lt;/li&gt;
    &lt;/ul&gt;
    &lt;div style=&quot;background: #fef2f2; border-left: 5px solid #ef4444; padding: 14px 18px; margin: 18px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #991b1b; font-size: 16px;&quot;&gt;⚠️ 現場の鉄則：本番リリースは必ず &lt;code&gt;git tag -a&lt;/code&gt; を使用すること&lt;/strong&gt;&lt;br/&gt;
        商用ソフトウェアやWebサービスの本番リリースでは、「誰が・いつ・どのような理由でリリースしたのか」というトレーサビリティ（追跡性）が監査上も極めて重要です。軽量タグを本番リリースに使うことは厳禁と心得ましょう。
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 25px;&quot;&gt;2. CLIでの本番マージ＆タグ打ちコマンド完全手順&lt;/h3&gt;
    &lt;p&gt;
        リリースブランチ &lt;code&gt;release/v1.0.0&lt;/code&gt; から &lt;code&gt;main&lt;/code&gt; へマージし、タグを打ってプッシュする標準的なコマンドフローです。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 18px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; overflow-x: auto; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 1. ローカルのmainブランチに切り替え、最新化&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch main&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; pull origin main&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 2. リリースブランチをマージ（必ず --no-ff でマージコミットを記録）&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; merge --no-ff release/v1.0.0 -m &lt;span style=&quot;color: #fde047;&quot;&gt;&quot;Merge branch &#39;release/v1.0.0&#39; into main for release&quot;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 3. マージコミットに対して注釈付きタグ（Annotated Tag）を打刻&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; tag -a v1.0.0 -m &lt;span style=&quot;color: #fde047;&quot;&gt;&quot;Release v1.0.0: 正式本番リリース（C# 顧客管理システム新機能・性能改善）&quot;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 4. mainブランチとタグをリモートリポジトリへプッシュ&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin main&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin v1.0.0 &lt;span style=&quot;color: #64748b;&quot;&gt;# または git push --tags&lt;/span&gt;
    &lt;/div&gt;
    &lt;p style=&quot;font-size: 15px; color: #475569;&quot;&gt;
        ※ &lt;code&gt;git push origin main&lt;/code&gt; だけではローカルで作成したタグはリモートに送信されません。必ず &lt;code&gt;git push origin v1.0.0&lt;/code&gt; （または &lt;code&gt;git push origin --tags&lt;/code&gt;）を実行してタグを明示的にプッシュする必要があります。
    &lt;/p&gt;

    &lt;!-- セクション④: C#アセンブリバージョンとGitHub Release連携 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【図解】C#現場でのバージョン管理（Directory.Build.props）とGitHub Releases連携&lt;/h2&gt;
    &lt;p&gt;
        C#（.NET 8 / .NET 9）の大規模プロジェクトでは、複数のプロジェクト（Web API、Domain、Infrastructure、Batch等）が存在します。&lt;br/&gt;
        各プロジェクトの &lt;code&gt;.csproj&lt;/code&gt; ファイルにそれぞれバージョン番号を手動で記載していると、更新漏れやバージョンの不一致事故が発生します。
    &lt;/p&gt;

    &lt;!-- 図解③: C#アセンブリとGitHub Release --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1zgEDaG9mU7z-pftx4hP2uXtMFmjOaO_B&quot; alt=&quot;C#アセンブリバージョンとGitHub Release連携&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】Directory.Build.propsの一元定義とGitHub ActionsによるRelease自動公開&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 25px;&quot;&gt;1. &lt;code&gt;Directory.Build.props&lt;/code&gt; によるソリューション全体の一括バージョン管理&lt;/h3&gt;
    &lt;p&gt;
        ソリューション（&lt;code&gt;.sln&lt;/code&gt;）と同じルートディレクトリに &lt;code&gt;Directory.Build.props&lt;/code&gt; ファイルを配置すると、配下のすべての &lt;code&gt;.csproj&lt;/code&gt; に自動で共通プロパティが適用されます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 18px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; overflow-x: auto; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;&amp;lt;!-- Directory.Build.props (ソリューションルートに配置) --&amp;gt;&lt;/span&gt;&lt;br/&gt;
        &amp;lt;&lt;span style=&quot;color: #f43f5e;&quot;&gt;Project&lt;/span&gt;&amp;gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;lt;&lt;span style=&quot;color: #f43f5e;&quot;&gt;PropertyGroup&lt;/span&gt;&amp;gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;Version&lt;/span&gt;&amp;gt;1.0.0&amp;lt;/&lt;span style=&quot;color: #38bdf8;&quot;&gt;Version&lt;/span&gt;&amp;gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;AssemblyVersion&lt;/span&gt;&amp;gt;1.0.0.0&amp;lt;/&lt;span style=&quot;color: #38bdf8;&quot;&gt;AssemblyVersion&lt;/span&gt;&amp;gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;FileVersion&lt;/span&gt;&amp;gt;1.0.0.0&amp;lt;/&lt;span style=&quot;color: #38bdf8;&quot;&gt;FileVersion&lt;/span&gt;&amp;gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;InformationalVersion&lt;/span&gt;&amp;gt;1.0.0+build.release&amp;lt;/&lt;span style=&quot;color: #38bdf8;&quot;&gt;InformationalVersion&lt;/span&gt;&amp;gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;Company&lt;/span&gt;&amp;gt;Our Enterprise Tech Inc.&amp;lt;/&lt;span style=&quot;color: #38bdf8;&quot;&gt;Company&lt;/span&gt;&amp;gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;Product&lt;/span&gt;&amp;gt;Customer Management System&amp;lt;/&lt;span style=&quot;color: #38bdf8;&quot;&gt;Product&lt;/span&gt;&amp;gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;lt;/&lt;span style=&quot;color: #f43f5e;&quot;&gt;PropertyGroup&lt;/span&gt;&amp;gt;&lt;br/&gt;
        &amp;lt;/&lt;span style=&quot;color: #f43f5e;&quot;&gt;Project&lt;/span&gt;&amp;gt;
    &lt;/div&gt;
    &lt;p&gt;
        リリース時には、この1箇所の &lt;code&gt;&amp;lt;Version&amp;gt;&lt;/code&gt; を &lt;code&gt;1.0.0&lt;/code&gt; に書き換えてコミットするだけで、全DLLやEXEのアセンブリ情報、SwaggerのAPIバージョン、NuGetパッケージ番号が一括で同期されます！
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 25px;&quot;&gt;2. タグプッシュをトリガーとしたGitHub Actions自動リリース連携&lt;/h3&gt;
    &lt;p&gt;
        &lt;code&gt;git push origin v1.0.0&lt;/code&gt; を行うと、GitHub Actionsが &lt;code&gt;tags: [&#39;v*&#39;]&lt;/code&gt; のイベントを検知し、自動的に本番ビルドを実行してGitHub ReleasesにZIP配布物とリリースノートを公開するワークフローが組めます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 18px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; overflow-x: auto; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# .github/workflows/release.yml&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #f43f5e;&quot;&gt;name&lt;/span&gt;: Production Release&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #f43f5e;&quot;&gt;on&lt;/span&gt;:&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f43f5e;&quot;&gt;push&lt;/span&gt;:&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #38bdf8;&quot;&gt;tags&lt;/span&gt;:&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #fde047;&quot;&gt;&#39;v*&#39;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #f43f5e;&quot;&gt;jobs&lt;/span&gt;:&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #38bdf8;&quot;&gt;build-and-release&lt;/span&gt;:&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f43f5e;&quot;&gt;runs-on&lt;/span&gt;: ubuntu-latest&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f43f5e;&quot;&gt;steps&lt;/span&gt;:&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #f43f5e;&quot;&gt;uses&lt;/span&gt;: actions/checkout@v4&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #f43f5e;&quot;&gt;name&lt;/span&gt;: Setup .NET&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f43f5e;&quot;&gt;uses&lt;/span&gt;: actions/setup-dotnet@v4&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f43f5e;&quot;&gt;with&lt;/span&gt;:&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #38bdf8;&quot;&gt;dotnet-version&lt;/span&gt;: &lt;span style=&quot;color: #fde047;&quot;&gt;&#39;8.0.x&#39;&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #f43f5e;&quot;&gt;name&lt;/span&gt;: Publish App&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f43f5e;&quot;&gt;run&lt;/span&gt;: dotnet publish -c Release -o ./publish&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #f43f5e;&quot;&gt;name&lt;/span&gt;: Create GitHub Release&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f43f5e;&quot;&gt;uses&lt;/span&gt;: softprops/action-gh-release@v2&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f43f5e;&quot;&gt;with&lt;/span&gt;:&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #38bdf8;&quot;&gt;generate_release_notes&lt;/span&gt;: &lt;span style=&quot;color: #a7f3d0;&quot;&gt;true&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #38bdf8;&quot;&gt;files&lt;/span&gt;: ./publish/*
    &lt;/div&gt;

    &lt;!-- セクション⑤: developへのマージバックとサイクルの完結 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【図解】developへのマージバックとリリースサイクルの完結&lt;/h2&gt;
    &lt;p&gt;
        「mainにマージしてタグを打ったから、これで本日のリリース業務は完了！」とPCを閉じてしまっては&lt;strong&gt;絶対にダメ&lt;/strong&gt;です！&lt;br/&gt;
        リリースサイクルにおける最大の落とし穴がここにあります。
    &lt;/p&gt;

    &lt;!-- 図解④: developへのマージバック --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1dN_4W46Ajp4n_EkqyDxqizXpYfWueFQk&quot; alt=&quot;developへのマージバックとサイクル完結&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】developへのマージバックによる先祖返り防止とリリースサイクルの完結&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 25px;&quot;&gt;1. なぜ「developへのマージバック」を忘れると悲劇が起きるのか？&lt;/h3&gt;
    &lt;p&gt;
        Day 22で学んだ通り、リリースブランチ（&lt;code&gt;release/v1.0.0&lt;/code&gt;）ではステージング検証中に発見された不具合の緊急修正コミット（&lt;code&gt;fix: ...&lt;/code&gt;）や、バージョン番号の更新コミットが行われています。&lt;br/&gt;
        もしこの修正内容を &lt;code&gt;develop&lt;/code&gt; ブランチ（次期バージョン v1.1.0 の開発本流）へ合流させずに放置した場合、何が起きるでしょうか？&lt;br/&gt;
        次回の v1.1.0 リリース時に、&lt;strong&gt;「v1.0.0 で苦労して直したはずのバグが、v1.1.0 で綺麗さっぱり復活する（先祖返り・リグレッション）」&lt;/strong&gt;という大惨事に見舞われます！
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #0369a1; font-size: 19px; margin-top: 25px;&quot;&gt;2. サイクルの完結手順（マージバックとブランチ削除）&lt;/h3&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 18px 20px; border-radius: 6px; font-family: Consolas, monospace; font-size: 14.5px; overflow-x: auto; margin: 15px 0;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 1. developブランチに切り替え、最新化&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch develop&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; pull origin develop&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 2. リリースブランチのバグ修正をdevelopへマージバック&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; merge --no-ff release/v1.0.0 -m &lt;span style=&quot;color: #fde047;&quot;&gt;&quot;Merge branch &#39;release/v1.0.0&#39; back into develop&quot;&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin develop&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 3. mainとdevelop双方への合流が完了したため、役目を終えたリリースブランチを安全に削除&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; branch -d release/v1.0.0&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin --delete release/v1.0.0
    &lt;/div&gt;
    &lt;p&gt;
        &lt;code&gt;git branch -d&lt;/code&gt; （小文字のd）を使えば、対象ブランチが完全にマージされていない場合にエラーで教えてくれるため、誤って未マージのコミットを消してしまう心配もありません。
    &lt;/p&gt;

    &lt;!-- セクション⑥: 実践CLIコマンド集 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ 現場で使える！実践CLIコマンド＆トラブルシューティング集&lt;/h2&gt;

    &lt;div style=&quot;background: #ffffff; border: 1px solid #e2e8f0; border-radius: 8px; padding: 18px; margin: 20px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #1e3a8a; font-size: 17px;&quot;&gt;📌 タグの一覧確認と詳細情報の表示&lt;/h4&gt;
        &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 12px 16px; border-radius: 4px; font-family: Consolas, monospace; font-size: 14px; margin-bottom: 8px;&quot;&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; tag -n &lt;span style=&quot;color: #64748b;&quot;&gt;# タグ名とメッセージを一覧表示&lt;/span&gt;&lt;br/&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; show v1.0.0 &lt;span style=&quot;color: #64748b;&quot;&gt;# タグの作成者、日時、メッセージ、コミット差分を詳細表示&lt;/span&gt;
        &lt;/div&gt;
        &lt;p style=&quot;margin: 0; font-size: 14.5px; color: #475569;&quot;&gt;
            &lt;code&gt;git show &amp;lt;tagname&amp;gt;&lt;/code&gt; を実行すると、注釈付きタグに付与された電子署名や作成者情報が即座に確認できます。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #ffffff; border: 1px solid #e2e8f0; border-radius: 8px; padding: 18px; margin: 20px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #1e3a8a; font-size: 17px;&quot;&gt;📌 誤って打ったタグの削除と差し替え手順&lt;/h4&gt;
        &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 12px 16px; border-radius: 4px; font-family: Consolas, monospace; font-size: 14px; margin-bottom: 8px;&quot;&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; tag -d v1.0.0 &lt;span style=&quot;color: #64748b;&quot;&gt;# ローカルのタグを削除&lt;/span&gt;&lt;br/&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin --delete v1.0.0 &lt;span style=&quot;color: #64748b;&quot;&gt;# リモートリポジトリのタグを削除&lt;/span&gt;
        &lt;/div&gt;
        &lt;p style=&quot;margin: 0; font-size: 14.5px; color: #475569;&quot;&gt;
            ※ 一度リモートに公開したタグの削除や差し替えは、他メンバーのローカルキャッシュとの不整合を招くため、チーム内への事前告知を徹底してください。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #ffffff; border: 1px solid #e2e8f0; border-radius: 8px; padding: 18px; margin: 20px 0;&quot;&gt;
        &lt;h4 style=&quot;margin: 0 0 10px 0; color: #1e3a8a; font-size: 17px;&quot;&gt;📌 過去のリリースポイント（タグ）から緊急調査・パッチブランチを作成&lt;/h4&gt;
        &lt;div style=&quot;background: #0f172a; color: #f8fafc; padding: 12px 16px; border-radius: 4px; font-family: Consolas, monospace; font-size: 14px; margin-bottom: 8px;&quot;&gt;
            &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; checkout -b hotfix/v1.0.1 v1.0.0 &lt;span style=&quot;color: #64748b;&quot;&gt;# v1.0.0タグの地点から直接ブランチを派生&lt;/span&gt;
        &lt;/div&gt;
        &lt;p style=&quot;margin: 0; font-size: 14.5px; color: #475569;&quot;&gt;
            本番で重大バグが発生した際も、タグ名を指定するだけで「リリース当時のコードベース」へ一瞬でタイムワープし、緊急ホットフィックスを開始できます。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- まとめセクション --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #3b82f6; border-radius: 10px; padding: 24px; margin: 40px 0;&quot;&gt;
        &lt;h3 style=&quot;margin: 0 0 15px 0; color: #1e3a8a; font-size: 21px;&quot;&gt;📌 本日のまとめと次回予告&lt;/h3&gt;
        &lt;p style=&quot;margin-bottom: 15px;&quot;&gt;
            本番リリースとタグ打刻は、開発チームがユーザーと交わす「品質保証の契約」です。今回の重要ポイントをおさらいしましょう。
        &lt;/p&gt;
        &lt;ul style=&quot;padding-left: 20px; line-height: 1.9;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;SVNのタグはただのフォルダコピー（変更可能）:&lt;/strong&gt; Gitのタグは特定コミットを暗号学的に固定する不変のピン留め。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;本番リリースは必ず注釈付きタグ（&lt;code&gt;git tag -a&lt;/code&gt;）:&lt;/strong&gt; 作成者、日時、詳細メッセージをメタデータとして永久保持する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;C#バージョンは &lt;code&gt;Directory.Build.props&lt;/code&gt; で一元化:&lt;/strong&gt; 複数プロジェクトのバージョンズレを防ぎ、タグプッシュからGitHub Releasesを自動生成。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;developへのマージバックを絶対忘れない:&lt;/strong&gt; リリースブランチの修正を次期開発本流へ合流させ、先祖返りを100%遮断する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;双方向合流の確認後にブランチ削除:&lt;/strong&gt; 役目を終えたブランチをクリーンアップし、プロジェクトを常に清潔に保つ。&lt;/li&gt;
        &lt;/ul&gt;
        &lt;div style=&quot;background: #eff6ff; padding: 14px 18px; border-radius: 6px; margin-top: 15px;&quot;&gt;
            &lt;strong style=&quot;color: #1d4ed8;&quot;&gt;次回予告【Day 24】: 【Case 4】緊急障害対応（ホットフィックス・パッチリリース）&lt;/strong&gt;&lt;br/&gt;
            本番環境で深刻なバグが発生！developや進行中のリリースブランチを一切汚さず、mainのv1.0.0タグから最速でホットフィックスブランチを切り、修正・検証・v1.0.1パッチリリース・全ブランチ統合を完了する「火消しの極意」を徹底伝授します！
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/3281009115311701485/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-23case-3.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3281009115311701485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3281009115311701485'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-23case-3.html' title='【Day 23】【Case 3】本番リリースとタグ打ち（安定バージョンの凍結）'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1F5w3ybkmcLPsUICLtBJZEIbDS5teDSte=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-3078704669800717486</id><published>2026-10-21T09:19:40.648+09:00</published><updated>2026-10-21T09:19:40.648+09:00</updated><title type='text'>【Day 25】複数環境設定の切り替え（docker-compose.override.yml） 〜ローカル開発とCI・本番の構成を安全に多重合成するベストプラクティスとC#環境分離設計〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1s4IFi4qfb3LKKM4a4deNi4xIAX4v8K8v&quot; alt=&quot;Day 25 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 25: 複数環境設定の切り替え（docker-compose.override.yml）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0fdf4; border-left: 6px solid #10b981; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;🔀&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #14532d; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;受講生の皆さん、お疲れ様です！ Docker/コンテナ実践講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回【Day 24】では、&lt;code&gt;.env&lt;/code&gt; と &lt;code&gt;.gitignore&lt;/code&gt; を駆使してパスワードや機密情報を安全に隔離し、Gitリポジトリをチーム共有するセキュリティ手法を学びました。&lt;br/&gt;
            これで安全なマルチコンテナ環境が整いましたが、次のステップとして&lt;strong&gt;「環境ごとの構成の違い」&lt;/strong&gt;という現場特有の壁に直面します！&lt;br/&gt;
            「開発環境ではホストPCからSQL ServerやRedisに直接GUIツールで繋ぎたいからポートを公開したい」「でも本番やCI環境では余計なポートは絶対に塞ぎたい」「ソースコードのホットリロードはローカルだけに適用したい」…&lt;br/&gt;
            環境ごとにYAMLファイルを丸ごとコピーして別名保存していませんか？&lt;br/&gt;
            本日【Day 25】は、Docker Compose最強の拡張機能である&lt;strong&gt;「&lt;code&gt;docker-compose.override.yml&lt;/code&gt; による構成の自動多重合成」&lt;/strong&gt;と、&lt;strong&gt;「C#（ASPNETCORE_ENVIRONMENT）と連動した環境切り替え設計」&lt;/strong&gt;を完全攻略します！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        Docker ComposeでWeb APIとDBを定義した &lt;code&gt;docker-compose.yml&lt;/code&gt; を運用していると、必ず以下のようなジレンマが生まれます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #fef2f2; border: 1px solid #fecaca; border-radius: 6px; padding: 18px 20px; margin: 20px 0; color: #991b1b; font-size: 15px;&quot;&gt;
        &lt;strong&gt;⚠️ 現場で陥りがちなアンチパターン（構成ファイルの丸ごとコピー増殖）：&lt;/strong&gt;&lt;br/&gt;
        開発用の設定と本番用の設定を分けたいあまり、&lt;code&gt;docker-compose.dev.yml&lt;/code&gt; と &lt;code&gt;docker-compose.prod.yml&lt;/code&gt; をそれぞれフルセットで作成してしまう。&lt;br/&gt;
        その結果、共通のDBサービス定義や環境変数に変更が入るたびに「両方のファイルを修正・同期」しなければならず、修正漏れによる本番障害が多発する…！
    &lt;/div&gt;
    &lt;p&gt;
        従来のオンプレミス運用でも、&lt;code&gt;web.config&lt;/code&gt; や設定ファイルを「開発サーバー用」「ステージング用」「本番用」と手動でコピー＆書き換えし、デプロイ時に事故を起こしていた歴史がありました。&lt;br/&gt;
        Docker Composeはこの問題を極めてスマートに解決する&lt;strong&gt;「override（上書き・合成）機構」&lt;/strong&gt;を標準で備えています。
    &lt;/p&gt;

    &lt;!-- 本日の達成目標ボックス --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #e2e8f0; border-radius: 8px; padding: 22px 24px; margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 14px; font-size: 18px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 50%; width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; font-size: 14px; margin-right: 10px;&quot;&gt;🎯&lt;/span&gt;
            本日の到達目標（ゴール宣言）
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #334155; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;Composeの自動多重合成（override）の仕組み:&lt;/strong&gt; &lt;code&gt;docker-compose.override.yml&lt;/code&gt; がデフォルトで自動読み込みされ、基本設定とマージされる挙動を理解する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;開発環境 vs 本番・CI環境の差分設計:&lt;/strong&gt; 共通設定（ベース）と、環境固有の差分（ポート・マウント・環境変数）を最小限のコードで分離する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;&lt;code&gt;-f&lt;/code&gt; オプションによる明示的合成:&lt;/strong&gt; 本番環境やCIパイプラインで特定のYAMLファイル同士を合成して起動するコマンド手順をマスターする。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;C#（ASP.NET Core）の環境切り替え連動:&lt;/strong&gt; &lt;code&gt;ASPNETCORE_ENVIRONMENT&lt;/code&gt; の値をComposeから注入し、&lt;code&gt;appsettings.Development.json&lt;/code&gt; と &lt;code&gt;appsettings.Production.json&lt;/code&gt; を安全に切り替える実装を習得する。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第2章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② Compose設定の自動多重合成（override）メカニズム&lt;/h2&gt;
    &lt;p&gt;
        まずは、Docker Composeが提供する「override機構」の基本ルールと、2つのファイルがどのように合体するのかを図解で確認しましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1ma_xg63SEiQtScI68Mc2V2T8iIo8lGsZ&quot; alt=&quot;Compose設定の自動合成（override）の仕組み&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】Compose設定の自動合成（override）の仕組み（基本設定 ＋ 上書き設定 ＝ 最終適用設定）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;暗黙のデフォルト：引数なしで2つのファイルが自動マージ&lt;/h3&gt;
    &lt;p&gt;
        Docker ComposeのCLI（&lt;code&gt;docker compose up&lt;/code&gt;）を実行した際、Composeはカレントディレクトリから以下の2つのファイルを&lt;strong&gt;自動的に順番に読み込み、メモリ上で合成（マージ）&lt;/strong&gt;します。
    &lt;/p&gt;
    &lt;ol style=&quot;color: #334155; line-height: 1.9; margin: 15px 0; padding-left: 22px;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;（第1読み込み）:&lt;/strong&gt; すべての環境で共有される基本設計図（サービス定義、コンテナ名、内部ネットワーク構成など）。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;&lt;code&gt;docker-compose.override.yml&lt;/code&gt;（第2読み込み）:&lt;/strong&gt; 第1の基本設計図に対して、開発者のローカル都合で上書きしたい項目だけを追記した差分ファイル。&lt;/li&gt;
    &lt;/ol&gt;
    &lt;p&gt;
        つまり、コマンド実行時に何もオプションを指定しなくても、自動的に &lt;code&gt;基本設定 ＋ override設定 ＝ 合成設定&lt;/code&gt; が完成してコンテナが起動します！
    &lt;/p&gt;

    &lt;div style=&quot;background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 6px; padding: 18px 20px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;color: #1e40af; margin-top: 0; margin-bottom: 10px; font-size: 16px;&quot;&gt;💡 マージ（合体）の基本ルール：値の上書き vs リストの追加&lt;/h4&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #1e3a8a; line-height: 1.8; font-size: 14.5px;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;スカラー値・辞書（キーと値のペア）:&lt;/strong&gt; &lt;code&gt;image:&lt;/code&gt; や &lt;code&gt;environment:&lt;/code&gt; の同じキーは、後から読み込まれた override ファイル側の値で&lt;strong&gt;上書き&lt;/strong&gt;されます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;リスト（配列形式の項目）:&lt;/strong&gt; &lt;code&gt;ports:&lt;/code&gt; や &lt;code&gt;volumes:&lt;/code&gt; などの配列は、両方のファイルの内容が&lt;strong&gt;追加（結合）&lt;/strong&gt;されます。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第3章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ ローカル開発用 vs 本番・CI用の構成差異と設計パターン&lt;/h2&gt;
    &lt;p&gt;
        なぜこの合成機構がこれほど重宝されるのでしょうか？&lt;br/&gt;
        それは、&lt;strong&gt;「ローカル開発環境」と「本番・ステージング環境」で求められる要件が真逆である&lt;/strong&gt;ためです。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1Pzka-xNfna0vGmpFHzt2O50_C07BBJs9&quot; alt=&quot;開発環境 vs 本番環境の構成差異&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】ローカル開発環境 vs 本番・CI環境の構成差異（ホットリロード重視 vs 堅牢・軽量重視）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        開発環境と本番環境の要件差異を整理したのが下表です。
    &lt;/p&gt;

    &lt;!-- 比較テーブル --&gt;
    &lt;div style=&quot;overflow-x: auto; margin: 25px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; text-align: left; font-size: 14.5px;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #0369a1; color: #ffffff;&quot;&gt;
                    &lt;th style=&quot;padding: 12px 14px; border: 1px solid #0284c7;&quot;&gt;設定項目&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 14px; border: 1px solid #0284c7;&quot;&gt;ローカル開発環境（override.yml）&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 14px; border: 1px solid #0284c7;&quot;&gt;本番・CI環境（prod.yml）&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; font-weight: bold;&quot;&gt;ポート公開（ports）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; color: #0369a1;&quot;&gt;&lt;code&gt;5000:80&lt;/code&gt;, &lt;code&gt;1433:1433&lt;/code&gt;（直接アクセス用）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; color: #b91c1c;&quot;&gt;非公開（リバースプロキシや内部NW経由）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; font-weight: bold;&quot;&gt;ソースコードマウント&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; color: #0369a1;&quot;&gt;バインドマウント（ホットリロード有効）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; color: #b91c1c;&quot;&gt;マウントなし（ビルド済みイメージのみ）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; font-weight: bold;&quot;&gt;ビルド方式&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; color: #0369a1;&quot;&gt;&lt;code&gt;build: .&lt;/code&gt;（ローカル最新コードからビルド）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; color: #15803d;&quot;&gt;&lt;code&gt;image: myregistry.io/myapp:1.2.0&lt;/code&gt;（検証済み固定）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; font-weight: bold;&quot;&gt;ASPNETCORE_ENVIRONMENT&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; color: #0369a1;&quot;&gt;&lt;code&gt;Development&lt;/code&gt;（Swagger有効・詳細エラー）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 14px; border: 1px solid #e2e8f0; color: #15803d;&quot;&gt;&lt;code&gt;Production&lt;/code&gt;（セキュアエラー・最適化）&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;実例：最小限の差分で記述する美しいYAML構成&lt;/h3&gt;
    &lt;p&gt;
        それでは、実際のYAMLコードで設計例を見てみましょう。&lt;br/&gt;
        まず、全環境共通のベース定義 &lt;code&gt;docker-compose.yml&lt;/code&gt; です。
    &lt;/p&gt;

    &lt;!-- YAMLコード例: 基本設定 --&gt;
    &lt;div style=&quot;background: #1e293b; color: #e2e8f0; border-radius: 8px; padding: 20px 22px; margin: 20px 0; font-family: Consolas, Monaco, monospace; font-size: 14px; overflow-x: auto; box-shadow: 0 4px 12px rgba(0,0,0,0.15);&quot;&gt;
        &lt;div style=&quot;color: #94a3b8; margin-bottom: 12px; font-size: 12.5px; border-bottom: 1px solid #334155; padding-bottom: 6px;&quot;&gt;# docker-compose.yml（Git共有する共通ベース設計図）&lt;/div&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;services&lt;/span&gt;:
  &lt;span style=&quot;color: #f472b6;&quot;&gt;webapi&lt;/span&gt;:
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;build&lt;/span&gt;:
      &lt;span style=&quot;color: #38bdf8;&quot;&gt;context&lt;/span&gt;: .
      &lt;span style=&quot;color: #38bdf8;&quot;&gt;dockerfile&lt;/span&gt;: Dockerfile
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;environment&lt;/span&gt;:
      - &lt;span style=&quot;color: #fde047;&quot;&gt;DOTNET_RUNNING_IN_CONTAINER=true&lt;/span&gt;
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;networks&lt;/span&gt;:
      - &lt;span style=&quot;color: #fde047;&quot;&gt;backend-network&lt;/span&gt;
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;depends_on&lt;/span&gt;:
      - &lt;span style=&quot;color: #fde047;&quot;&gt;sqlserver&lt;/span&gt;

  &lt;span style=&quot;color: #f472b6;&quot;&gt;sqlserver&lt;/span&gt;:
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;image&lt;/span&gt;: mcr.microsoft.com/mssql/server:2022-latest
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;environment&lt;/span&gt;:
      - &lt;span style=&quot;color: #fde047;&quot;&gt;ACCEPT_EULA=Y&lt;/span&gt;
      - &lt;span style=&quot;color: #fde047;&quot;&gt;MSSQL_SA_PASSWORD=${SA_PASSWORD}&lt;/span&gt;
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;networks&lt;/span&gt;:
      - &lt;span style=&quot;color: #fde047;&quot;&gt;backend-network&lt;/span&gt;

&lt;span style=&quot;color: #38bdf8;&quot;&gt;networks&lt;/span&gt;:
  &lt;span style=&quot;color: #f472b6;&quot;&gt;backend-network&lt;/span&gt;:
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;driver&lt;/span&gt;: bridge
    &lt;/div&gt;

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

    &lt;!-- YAMLコード例: override設定 --&gt;
    &lt;div style=&quot;background: #1e293b; color: #e2e8f0; border-radius: 8px; padding: 20px 22px; margin: 20px 0; font-family: Consolas, Monaco, monospace; font-size: 14px; overflow-x: auto; box-shadow: 0 4px 12px rgba(0,0,0,0.15);&quot;&gt;
        &lt;div style=&quot;color: #94a3b8; margin-bottom: 12px; font-size: 12.5px; border-bottom: 1px solid #334155; padding-bottom: 6px;&quot;&gt;# docker-compose.override.yml（ローカル開発者向けの差分ファイル）&lt;/div&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;services&lt;/span&gt;:
  &lt;span style=&quot;color: #f472b6;&quot;&gt;webapi&lt;/span&gt;:
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;ports&lt;/span&gt;:
      - &lt;span style=&quot;color: #fde047;&quot;&gt;&quot;5000:8080&quot;&lt;/span&gt;        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# ホストPCからSwaggerやAPIを直接叩くためのポート開放&lt;/span&gt;
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;environment&lt;/span&gt;:
      - &lt;span style=&quot;color: #fde047;&quot;&gt;ASPNETCORE_ENVIRONMENT=Development&lt;/span&gt;
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;volumes&lt;/span&gt;:
      - &lt;span style=&quot;color: #fde047;&quot;&gt;./src:/app/src&lt;/span&gt;      &lt;span style=&quot;color: #94a3b8;&quot;&gt;# ソースコード変更の即時反映用（ホットリロード）&lt;/span&gt;

  &lt;span style=&quot;color: #f472b6;&quot;&gt;sqlserver&lt;/span&gt;:
    &lt;span style=&quot;color: #a78bfa;&quot;&gt;ports&lt;/span&gt;:
      - &lt;span style=&quot;color: #fde047;&quot;&gt;&quot;1433:1433&quot;&lt;/span&gt;        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# SSMSやVS Codeのmsoql拡張から直接テーブルを見るための開放&lt;/span&gt;
    &lt;/div&gt;

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

    &lt;!-- 第4章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ CLIコマンド完全制覇：-f オプションと config 検証&lt;/h2&gt;
    &lt;p&gt;
        「ローカル開発では自動マージされるのは分かったけれど、本番環境やCI/CDパイプラインではどうやって別ファイルを適用するの？」&lt;br/&gt;
        ここで使うのが、Compose CLIの &lt;code&gt;-f&lt;/code&gt;（&lt;code&gt;--file&lt;/code&gt;）フラグです！
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1TRBBZFyp5s4NjTZi-fLWZxX6DaC7k8We&quot; alt=&quot;-f オプションによる複数ファイル指定の3ステップ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】-f オプションによる複数ファイル指定と検証の3ステップフロー（暗黙合成・明示指定・config確認）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;-f オプションを指定した瞬間の重要ルール&lt;/h3&gt;
    &lt;div style=&quot;background: #fffbeb; border: 1px solid #fef3c7; border-radius: 6px; padding: 18px 20px; margin: 20px 0; color: #92400e; font-size: 15px;&quot;&gt;
        &lt;strong&gt;⚠️ 絶対に覚えておくべきComposeの挙動ルール：&lt;/strong&gt;&lt;br/&gt;
        &lt;code&gt;docker compose&lt;/code&gt; に一度でも &lt;code&gt;-f&lt;/code&gt; オプションを指定すると、&lt;strong&gt;「&lt;code&gt;docker-compose.override.yml&lt;/code&gt; の暗黙の自動読み込みが無効化」&lt;/strong&gt;されます！&lt;br/&gt;
        したがって、本番用ファイル（例: &lt;code&gt;docker-compose.prod.yml&lt;/code&gt;）を適用したい場合は、基本設定と本番用設定の両方を &lt;code&gt;-f&lt;/code&gt; で明示的に渡します。
    &lt;/div&gt;

    &lt;!-- CLIコマンド一覧 --&gt;
    &lt;div style=&quot;background: #1e293b; color: #e2e8f0; border-radius: 8px; padding: 20px 22px; margin: 20px 0; font-family: Consolas, Monaco, monospace; font-size: 14.5px; overflow-x: auto;&quot;&gt;
        &lt;div style=&quot;color: #94a3b8; margin-bottom: 8px; font-size: 12px;&quot;&gt;# 1. ローカル開発環境の起動（暗黙的に compose.yml + override.yml が合成される）&lt;/div&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;$&lt;/span&gt; docker compose up -d&lt;br/&gt;&lt;br/&gt;
        &lt;div style=&quot;color: #94a3b8; margin-bottom: 8px; font-size: 12px;&quot;&gt;# 2. 本番・ステージング環境の起動（ベースとprod用を明示的に合成して起動）&lt;/div&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;$&lt;/span&gt; docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d&lt;br/&gt;&lt;br/&gt;
        &lt;div style=&quot;color: #94a3b8; margin-bottom: 8px; font-size: 12px;&quot;&gt;# 3. 超便利！実際に合成された最終YAML設定の確認（ドライラン）&lt;/div&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;$&lt;/span&gt; docker compose config
    &lt;/div&gt;

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

    &lt;!-- 第5章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ C# ASP.NET Core の環境変数切り替え（ASPNETCORE_ENVIRONMENT）実践&lt;/h2&gt;
    &lt;p&gt;
        最後に、C#（.NET 8/9）エンジニアの現場視点で最も重要な「コンテナ内アプリの環境連動」を実装しましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1NiplOMnmxeqfItYeo2znHj2d8P-s9mkl&quot; alt=&quot;C# ASP.NET Core の環境変数切り替え&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】C#（ASP.NET Core）の環境切り替えフロー（ComposeからASPNETCORE_ENVIRONMENTを注入する3ステップ）&lt;/div&gt;
    &lt;/div&gt;
    

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

    &lt;!-- C#コード例 --&gt;
    &lt;div style=&quot;background: #1e293b; color: #e2e8f0; border-radius: 8px; padding: 20px 22px; margin: 20px 0; font-family: Consolas, Monaco, monospace; font-size: 14px; overflow-x: auto; box-shadow: 0 4px 12px rgba(0,0,0,0.15);&quot;&gt;
        &lt;div style=&quot;color: #94a3b8; margin-bottom: 12px; font-size: 12.5px; border-bottom: 1px solid #334155; padding-bottom: 6px;&quot;&gt;// Program.cs（ASP.NET Core 8.0 / 9.0）&lt;/div&gt;
&lt;span style=&quot;color: #38bdf8;&quot;&gt;var&lt;/span&gt; builder = &lt;span style=&quot;color: #4ade80;&quot;&gt;WebApplication&lt;/span&gt;.CreateBuilder(args);

&lt;span style=&quot;color: #94a3b8;&quot;&gt;// 1. コントローラーとSwaggerサービスの登録&lt;/span&gt;
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

&lt;span style=&quot;color: #38bdf8;&quot;&gt;var&lt;/span&gt; app = builder.Build();

&lt;span style=&quot;color: #94a3b8;&quot;&gt;// 2. 環境変数（ASPNETCORE_ENVIRONMENT）に基づく自動分岐&lt;/span&gt;
&lt;span style=&quot;color: #f472b6;&quot;&gt;if&lt;/span&gt; (app.Environment.IsDevelopment())
{
    &lt;span style=&quot;color: #94a3b8;&quot;&gt;// ローカル開発時のみSwagger UIを有効化＆詳細エラー表示&lt;/span&gt;
    app.UseSwagger();
    app.UseSwaggerUI(c =&gt;
    {
        c.SwaggerEndpoint(&lt;span style=&quot;color: #fde047;&quot;&gt;&quot;/swagger/v1/swagger.json&quot;&lt;/span&gt;, &lt;span style=&quot;color: #fde047;&quot;&gt;&quot;My API Dev v1&quot;&lt;/span&gt;);
    });
    app.UseDeveloperExceptionPage();
}
&lt;span style=&quot;color: #f472b6;&quot;&gt;else&lt;/span&gt;
{
    &lt;span style=&quot;color: #94a3b8;&quot;&gt;// 本番・ステージング環境では安全な汎用エラーハンドラーとHSTSを強制&lt;/span&gt;
    app.UseExceptionHandler(&lt;span style=&quot;color: #fde047;&quot;&gt;&quot;/error&quot;&lt;/span&gt;);
    app.UseHsts();
}

app.UseRouting();
app.UseAuthorization();
app.MapControllers();

app.Run();
    &lt;/div&gt;

    &lt;div style=&quot;background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 6px; padding: 18px 20px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;color: #15803d; margin-top: 0; margin-bottom: 8px; font-size: 16px;&quot;&gt;✨ appsettings.*.json の自動マージチェーン&lt;/h4&gt;
        &lt;p style=&quot;margin: 0; color: #166534; font-size: 14.5px; line-height: 1.8;&quot;&gt;
            &lt;code&gt;ASPNETCORE_ENVIRONMENT=Development&lt;/code&gt; が注入された場合、.NETランタイムはまず &lt;code&gt;appsettings.json&lt;/code&gt; を読み込み、その直後に &lt;code&gt;appsettings.Development.json&lt;/code&gt; の値で上書き合成します。&lt;br/&gt;
            さらに前回学んだ Composeの環境変数（&lt;code&gt;ConnectionStrings__*&lt;/code&gt;）が最優先で重ね合わされるため、&lt;strong&gt;「共通設定 ➡ 環境別JSON ➡ コンテナ環境変数」の美しい3層カスケード構造&lt;/strong&gt;が完成します！
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- まとめセクション --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ 本日のまとめと理解度チェック&lt;/h2&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #cbd5e1; border-radius: 8px; padding: 22px 24px; margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 14px; font-size: 18px;&quot;&gt;💡 本日の重要ポイント総まとめ&lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #334155; line-height: 1.9;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;設定の共通化とoverrideの役割:&lt;/strong&gt; 全環境で共通のインフラ基盤は &lt;code&gt;docker-compose.yml&lt;/code&gt; に集約し、開発固有のポートやマウントは &lt;code&gt;docker-compose.override.yml&lt;/code&gt; に切り出す。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;暗黙の自動マージと -f による制御:&lt;/strong&gt; 引数なしの &lt;code&gt;docker compose up&lt;/code&gt; は override.yml を自動適用する。本番・CIでは &lt;code&gt;-f compose.yml -f compose.prod.yml&lt;/code&gt; で明示指定する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;docker compose config の活用:&lt;/strong&gt; 複数ファイルがどう合成されたかをコンテナ起動前にコマンド一発で可視化・点検する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;C#（ASPNETCORE_ENVIRONMENT）の連携:&lt;/strong&gt; Composeから注入された環境名に応じて、Swaggerの有効化や &lt;code&gt;appsettings.Development.json&lt;/code&gt; が自動反映され、安全な環境分離が実現する。&lt;/li&gt;
        &lt;/ul&gt;
        &lt;div style=&quot;margin-top: 15px; padding-top: 12px; border-top: 1px dashed #86efac; font-size: 15px; color: #14532d;&quot;&gt;
            &lt;strong&gt;次回【Day 26】予告:&lt;/strong&gt;&lt;br/&gt;
            『docker compose up / down / build の実務コマンド完全マスター』〜バックグラウンド起動（-d）、差分再ビルド（--build）、コンテナ・ボリューム破棄（down -v）の実務頻出ワークフロー〜
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/3078704669800717486/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-25docker-composeoverrideyml-cic.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3078704669800717486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3078704669800717486'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-25docker-composeoverrideyml-cic.html' title='【Day 25】複数環境設定の切り替え（docker-compose.override.yml） 〜ローカル開発とCI・本番の構成を安全に多重合成するベストプラクティスとC#環境分離設計〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1s4IFi4qfb3LKKM4a4deNi4xIAX4v8K8v=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-3055045573810663125</id><published>2026-10-20T18:12:47.855+09:00</published><updated>2026-10-20T18:12:47.855+09:00</updated><title type='text'>【Day 22】【Case 2】テスト・結合フェーズ（ステージング環境でのバグ出しと収束）</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/12GU_npmaUcw6TsvnyJOBPLIbhN-Rlxh9&quot; alt=&quot;Day 22 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 22】テスト・結合フェーズにおけるリリースブランチ運用とバグ収束&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 21では、複数人のC#エンジニアがスプリント並行開発を進める際の「トピックブランチ完全隔離」と「毎朝のリベース習慣」を学びました。&lt;br/&gt;
            本日のDay 22は、第5部 ケーススタディの第2弾として、開発プロジェクトの中で最もプレッシャーがかかる&lt;strong&gt;【テスト・結合フェーズ（ステージング環境でのバグ出しと収束）】&lt;/strong&gt;を徹底解説します！&lt;br/&gt;
            Subversion (SVN) や Visual SourceSafe (VSS) で開発してきたベテランエンジニアの方なら、「リリース前テストが始まったので、今日から trunk へのコミットは全面禁止です！」というアナウンスに頭を抱えた経験があるのではないでしょうか。&lt;br/&gt;
            テスト中のバグ修正と次期バージョンの新機能開発が同じ場所で行われていたため、開発チーム全体が「手待ち（足止め）」状態に陥っていたのです。&lt;br/&gt;
            しかしGitなら、&lt;strong&gt;リリースブランチ（&lt;code&gt;release/v1.0.0&lt;/code&gt;）&lt;/strong&gt;を活用することで、QA・結合テストでのバグ修正だけを綺麗に収束させつつ、次期機能開発チームは &lt;code&gt;develop&lt;/code&gt; で1秒も止まることなく爆速開発を継続できます。&lt;br/&gt;
            本日は、リリースブランチの切り方、ステージング環境へのデプロイ、C#での厳格なバグ修正コミットルール、そしてリリース完了時に絶対に欠かせない「双方向マージバック（先祖返り防止）」の実践テクニックを完全伝授します！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        システム開発が終盤に差し掛かると、QA（品質保証）チームやテスターによる結合テスト・受託受け入れテストがステージング環境で行われます。&lt;br/&gt;
        このフェーズで最も恐ろしいのは、&lt;strong&gt;「テスト中の安定版コードに、未完成の次期新機能が紛れ込んでしまうこと」&lt;/strong&gt;です。&lt;br/&gt;
        Gitのリリースブランチ運用（Git Flow / GitLab Flow等）を正しく理解していれば、「テスト対象のバージョン」と「次期開発の本流」を物理的にブランチで分離し、極めて安全かつ迅速に製品を本番公開へと導くことができます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;SVNの「テスト中コミット禁止令（開発凍結）」とGitのリリースブランチ隔離の違いを理解する&lt;/li&gt;
            &lt;li&gt;リリースブランチ（&lt;code&gt;release/v1.0.0&lt;/code&gt;）の作成タイミングと「フィーチャーフリーズ」の意義を把握する&lt;/li&gt;
            &lt;li&gt;ステージング環境への自動デプロイとC#（.NET）プロジェクトにおける結合テスト検証フローを身につける&lt;/li&gt;
            &lt;li&gt;テスト期間中の厳格コミット方針（新機能追加の全面禁止とバグ修正コミットの書き方）を習得する&lt;/li&gt;
            &lt;li&gt;リリース完了時の「双方向マージバック（mainとdevelopへのマージ）」により先祖返り（バグ復活）を100%防止する&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: SVN開発凍結 vs Gitリリースブランチ隔離 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】テスト期間中の開発ブロック対比：SVNの開発凍結 vs Gitのリリースブランチ隔離&lt;/h2&gt;
    &lt;p&gt;
        まずは、SVNなどの集中型バージョン管理とGitにおける「テスト期間中のチーム全体の動き」を比較してみましょう。
    &lt;/p&gt;

    &lt;!-- 図解①: SVN vs Git --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/12a9Q_4T8xr9tSzCsQrbLrUVdXV7UBGOG&quot; alt=&quot;テスト期間中の開発ブロック対比&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】SVNの「開発凍結」vs Gitの「リリースブランチ完全隔離」&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;開発凍結（コミット禁止令）の悲劇 vs リリースブランチの隔離力&lt;/h3&gt;
    &lt;ul style=&quot;line-height: 1.95; padding-left: 25px;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;SVNの悲劇（全員の手が止まる開発凍結）&lt;/strong&gt;: SVNではブランチの取り回しが難しいため、テスト期間に入ると「本番リリースまで trunk へのコミットは禁止！」というお触れが出ます。次期バージョンの機能を作りたくてもコミットできないため、ローカルにファイルを退避したり、開発自体が完全にストップして膨大な工数ロスが発生していました。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Gitの理想（リリースブランチによる完全並行）&lt;/strong&gt;: Gitでは、テスト開始の瞬間に &lt;code&gt;develop&lt;/code&gt; から &lt;code&gt;release/v1.0.0&lt;/code&gt; を分岐させます。ステージング環境にはこのブランチだけをデプロイし、QAチームがバグ出しを行います。次期機能（v1.1.0向け）を開発するメンバーは、そのまま &lt;code&gt;develop&lt;/code&gt; 上で何事もなかったかのように開発を続行できます。チームの生産性が1ミリも落ちません！&lt;/li&gt;
    &lt;/ul&gt;

    &lt;!-- セクション③: リリースブランチのライフサイクル --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【図解】リリースブランチのライフサイクル（分岐から収束まで）&lt;/h2&gt;
    &lt;p&gt;
        リリースブランチが生まれてから役割を終えるまでのライフサイクルは、以下の4つの明確なステップで進行します。
    &lt;/p&gt;

    &lt;!-- 図解②: リリースブランチライフサイクル --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1w2BsR6-XSAURyFa23VxfJClYpeQ7-Bvi&quot; alt=&quot;リリースブランチのライフサイクル&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】develop分岐からステージング検証、バグ収束までの4ステップ&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;リリースブランチ運用の4ステップ&lt;/h3&gt;
    &lt;ol style=&quot;line-height: 2.1; padding-left: 25px; margin: 18px 0;&quot;&gt;
        &lt;li&gt;
            &lt;strong&gt;① 分岐とフィーチャーフリーズ（機能追加の凍結）&lt;/strong&gt;:&lt;br/&gt;
            リリースターゲットの全機能が &lt;code&gt;develop&lt;/code&gt; に揃ったら、リリースブランチを切ります。&lt;br/&gt;
            &lt;code&gt;git switch -c release/v1.0.0 develop&lt;/code&gt;&lt;br/&gt;
            この瞬間以降、このブランチには&lt;strong&gt;「新しい機能の追加（feature）」は一切禁止&lt;/strong&gt;となります。
        &lt;/li&gt;
        &lt;li&gt;
            &lt;strong&gt;② ステージング環境へのデプロイと検証開始&lt;/strong&gt;:&lt;br/&gt;
            GitHub Actions などのCI/CDパイプラインにより、&lt;code&gt;release/v1.0.0&lt;/code&gt; がプッシュされると自動的にステージング環境へビルド・デプロイされます。QA担当者やクライアントが受け入れテストを開始します。
        &lt;/li&gt;
        &lt;li&gt;
            &lt;strong&gt;③ バグ修正コミットの集中投下&lt;/strong&gt;:&lt;br/&gt;
            テストで不具合が発見された場合、開発者は &lt;code&gt;release/v1.0.0&lt;/code&gt; に対して直接修正コミット（または修正用トピックブランチからのPR）を投入します。修正されるたびにステージングへ即時反映され、再テストが行われます。
        &lt;/li&gt;
        &lt;li&gt;
            &lt;strong&gt;④ 収束とリリースサインオフ&lt;/strong&gt;:&lt;br/&gt;
            すべての重要バグ（Blocker/Critical/Major）が解消され、全自動テスト（E2E、結合テスト）がグリーンになれば、リリースブランチの目的は達成です。本番リリース作業へと移行します。
        &lt;/li&gt;
    &lt;/ol&gt;

    &lt;!-- セクション④: C#現場でのステージング検証と修正方針 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【現場実践】C#現場でのステージング検証とバグ修正コミットの鉄則&lt;/h2&gt;
    &lt;p&gt;
        .NET / C# のエンタープライズ現場では、ステージング環境特有の設定やデータベースとの結合テストが行われます。&lt;br/&gt;
        このフェーズで絶対に守るべき「3大鉄則」を押さえておきましょう。
    &lt;/p&gt;

    &lt;!-- 図解③: C#現場でのステージング検証 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/10HjBiTlV5nTMEwdXpprFWgrdv_Gi0rf1&quot; alt=&quot;C#現場でのステージング検証と修正方針&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】C# / .NET 現場でのステージング検証とバグ修正コミットの鉄則&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #2563eb; padding: 18px 20px; margin: 25px 0; border-radius: 6px;&quot;&gt;
        &lt;strong style=&quot;color: #1e40af; font-size: 16.5px;&quot;&gt;🛠️ C# / .NET 現場での3大鉄則&lt;/strong&gt;&lt;br/&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;鉄則1：環境設定の厳格分離（appsettings.Staging.json）&lt;/strong&gt;&lt;br/&gt;
            接続文字列や外部APIエンドポイントは &lt;code&gt;appsettings.Staging.json&lt;/code&gt; に分離し、コード本体にハードコードしないこと。環境変数やAzure Key Vaultから注入する設計にしておくことで、デプロイ事故を防ぎます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;鉄則2：新機能の「ついでコミット」は即死級の重罪&lt;/strong&gt;&lt;br/&gt;
            「ちょっと時間が余ったから次の便利な機能も入れておこう」は絶対に厳禁！ 1つの余計なコード変更が予期せぬサイドエフェクト（退行バグ）を引き起こし、テスト工数を倍増させます。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;鉄則3：コミットメッセージは明確に &quot;fix:&quot; で打つ&lt;/strong&gt;&lt;br/&gt;
            &lt;code&gt;fix(payment): タイムアウト時の再試行リクエストで2重決済になる不具合を修正 (#412)&lt;/code&gt; のように、Conventional Commitsに従い、修正の対象とチケット番号を明記します。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑤: リリース完了時の双方向マージバック --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【最重要】リリース完了時の双方向マージバック：先祖返りを100%防止する&lt;/h2&gt;
    &lt;p&gt;
        テストが完了し、本番環境へのリリースが決定したとき、&lt;strong&gt;多くの現場が一度はやらかす「最大の落とし穴」&lt;/strong&gt;があります。&lt;br/&gt;
        それは、&lt;strong&gt;「リリースブランチで行ったバグ修正を、developブランチへ戻し忘れること」&lt;/strong&gt;です！
    &lt;/p&gt;

    &lt;!-- 図解④: 双方向マージバック --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1nTUm4A411qR201Amw3KlwZ5j5glTwgwK&quot; alt=&quot;リリース完了時の双方向マージバック&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】mainへの本番反映とdevelopへの合流（先祖返り防止）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;先祖返り（リグレッション）の恐怖と解決手順&lt;/h3&gt;
    &lt;p&gt;
        &lt;code&gt;release/v1.0.0&lt;/code&gt; でせっかく直したバグを &lt;code&gt;main&lt;/code&gt; だけにマージして満足してしまうと、次期バージョン（v1.1.0）を &lt;code&gt;develop&lt;/code&gt; からリリースした際、&lt;strong&gt;「前に直したはずのバグが再び大復活する（先祖返り）」&lt;/strong&gt;という大惨事が発生します。&lt;br/&gt;
        これを防ぐため、リリース完了時は必ず以下の「双方向マージバック」を行います。
    &lt;/p&gt;

    &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 20px 22px; border-radius: 8px; margin: 20px 0; font-family: &#39;Consolas&#39;, &#39;Courier New&#39;, monospace; font-size: 15px; line-height: 1.7; overflow-x: auto;&quot;&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# ① main（本番）へマージして製品タグを打つ&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch main&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; merge --no-ff release/v1.0.0&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; tag -a v1.0.0 -m &quot;Release version 1.0.0&quot;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# ② 【超重要】develop（次期開発の本流）へも必ずマージバック！&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; switch develop&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; merge --no-ff release/v1.0.0&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# ③ 役目を終えたリリースブランチを安全に削除&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; branch -d release/v1.0.0&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; push origin --delete release/v1.0.0
    &lt;/div&gt;

    &lt;!-- セクション⑥: まとめと次回予告 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ 現場の実践まとめ＆次回予告&lt;/h2&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #cbd5e1; border-radius: 8px; padding: 22px 24px; margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;margin-top: 0; color: #1e3a8a; font-size: 19px;&quot;&gt;📌 本日の最重要ポイントまとめ&lt;/h3&gt;
        &lt;ul style=&quot;line-height: 1.95; padding-left: 22px; margin-bottom: 0;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;リリースブランチで隔離せよ&lt;/strong&gt;: SVNの「テスト中コミット禁止（開発凍結）」を撤廃し、&lt;code&gt;release/*&lt;/code&gt; ブランチを切ることでQAテストと次期開発を完全並行化する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;フィーチャーフリーズの徹底&lt;/strong&gt;: リリースブランチには新機能を一切持ち込まず、QAで発見されたバグ修正（fix）のみを集中投入する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;ステージング環境の自動連携&lt;/strong&gt;: C# / .NET では &lt;code&gt;appsettings.Staging.json&lt;/code&gt; で安全に設定を切り替え、CI/CDで迅速に結合検証を進める。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;双方向マージバックの鉄則&lt;/strong&gt;: リリース完了時は &lt;code&gt;main&lt;/code&gt;（本番タグ）だけでなく、必ず &lt;code&gt;develop&lt;/code&gt; へもマージバックして修正の先祖返り（バグ復活）を未然に防ぐ。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #f0fdf4; border-left: 5px solid #16a34a; padding: 18px 20px; margin: 30px 0; border-radius: 6px;&quot;&gt;
        &lt;strong style=&quot;color: #15803d; font-size: 17px;&quot;&gt;🚀 次回予告：Day 23&lt;/strong&gt;&lt;br/&gt;
        &lt;p style=&quot;margin: 8px 0 0 0; line-height: 1.85;&quot;&gt;
            次回は、第5部 ケーススタディの第3弾！&lt;br/&gt;
            &lt;strong&gt;【Day 23: 【Case 3】本番リリースとタグ打ち（安定バージョンの凍結）】&lt;/strong&gt;をお届けします！&lt;br/&gt;
            ステージングテストをクリアしたコードを本番環境へ安全に反映させ、不変のバージョン番号（セマンティックバージョニング）を付与する「タグ打ちと本番リリース」の完全手順を徹底解説します。お楽しみに！
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/3055045573810663125/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-22case-2.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3055045573810663125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/3055045573810663125'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-22case-2.html' title='【Day 22】【Case 2】テスト・結合フェーズ（ステージング環境でのバグ出しと収束）'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/12GU_npmaUcw6TsvnyJOBPLIbhN-Rlxh9=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-5169000669903106835</id><published>2026-10-20T09:22:14.547+09:00</published><updated>2026-10-20T09:22:14.547+09:00</updated><title type='text'>【Day 24】docker-compose.yml のGit共有と .env のGit除外ルール 〜パスワード・接続文字列の漏洩を防ぐ安全なチーム開発とC#環境変数注入設計〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1GJFvmbK3x8WV6R1wk8CbpCrsAWOPYWmk&quot; alt=&quot;Day 24 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 24: docker-compose.yml のGit共有と .env のGit除外ルール&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0fdf4; border-left: 6px solid #10b981; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;🔐&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #14532d; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;受講生の皆さん、お疲れ様です！ Docker/コンテナ実践講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回【Day 23】では、Web API ＋ SQL Server ＋ Redis という本格的なモダン3層コンテナ構成をDocker Composeで立ち上げました。&lt;br/&gt;
            チーム開発でこの便利な環境を共有しようとした時、&lt;strong&gt;絶対に避けて通れない最重要テーマが「機密情報（シークレット）のセキュリティ管理」&lt;/strong&gt;です！&lt;br/&gt;
            YAMLファイルに書かれたデータベースのパスワードや接続文字列を、そのままGitにコミットしてしまっていませんか？&lt;br/&gt;
            本日【Day 24】は、設計図（&lt;code&gt;docker-compose.yml&lt;/code&gt;）を安全にチーム共有しながら、パスワードを完全にGitから隔離する&lt;strong&gt;「&lt;code&gt;.env&lt;/code&gt; と &lt;code&gt;.gitignore&lt;/code&gt; によるセキュリティ運用」&lt;/strong&gt;と、&lt;strong&gt;「C#（IConfiguration）への環境変数注入設計」&lt;/strong&gt;を徹底解説します！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        「docker-compose.yml が便利だから、Gitリポジトリにプッシュしてチームメンバーにも共有しよう！」&lt;br/&gt;
        そう思った瞬間、ふと手が止まった経験はありませんか？
    &lt;/p&gt;
    &lt;div style=&quot;background: #fef2f2; border: 1px solid #fecaca; border-radius: 6px; padding: 18px 20px; margin: 20px 0; color: #991b1b; font-size: 15px;&quot;&gt;
        &lt;strong&gt;⚠️ 現場で頻発する危険なシチュエーション：&lt;/strong&gt;&lt;br/&gt;
        &lt;code&gt;MSSQL_SA_PASSWORD: &quot;MyStrongPassword123!&quot;&lt;/code&gt; と書かれたComposeファイルを、そのままGitリポジトリへコミット＆プッシュ。&lt;br/&gt;
        その瞬間、GitHubや社内GitLabの全閲覧者に対してデータベースの管理者パスワードが丸見えになり、コミット履歴（git log）にも永久に刻み込まれてしまう…！
    &lt;/div&gt;
    &lt;p&gt;
        オンプレミスや従来のWindowsサーバー運用では、サーバー上の &lt;code&gt;web.config&lt;/code&gt; や構築手順書のExcelにパスワードを直接書き込み、閉じたネットワーク内で管理していました。&lt;br/&gt;
        しかし、インフラ構成をコードで管理する&lt;strong&gt;IaC（Infrastructure as Code）やGit中心のチーム開発&lt;/strong&gt;においては、この旧来の感覚のまま作業すると&lt;strong&gt;「即座に重大なセキュリティインシデント」&lt;/strong&gt;へと直結します。
    &lt;/p&gt;

    &lt;!-- 本日の達成目標ボックス --&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #e2e8f0; border-radius: 8px; padding: 22px 24px; margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #0f172a; margin-top: 0; margin-bottom: 14px; font-size: 18px; display: flex; align-items: center;&quot;&gt;
            &lt;span style=&quot;background: #0db7ed; color: #ffffff; border-radius: 50%; width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; font-size: 14px; margin-right: 10px;&quot;&gt;🎯&lt;/span&gt;
            本日の到達目標（ゴール宣言）
        &lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #334155; line-height: 1.85;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;平文コミットの危険性とGitの履歴性質:&lt;/strong&gt; なぜコードやYAMLにパスワードを直書きしてはいけないのか、漏洩のメカニズムを理解する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Gitコミット対象 vs 除外の境界線:&lt;/strong&gt; &lt;code&gt;docker-compose.yml&lt;/code&gt; / &lt;code&gt;.env.example&lt;/code&gt;（Git管理）と &lt;code&gt;.env&lt;/code&gt;（.gitignore除外）の完璧な棲み分けを身につける。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Docker Compose の変数展開仕様:&lt;/strong&gt; &lt;code&gt;.env&lt;/code&gt; ファイルがComposeによって自動読み込みされ、&lt;code&gt;${VARIABLE}&lt;/code&gt; に置換される仕組みをマスターする。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;C#（ASP.NET Core）へのセキュア設定注入:&lt;/strong&gt; &lt;code&gt;appsettings.json&lt;/code&gt; のデフォルト値を、コンテナ実行時の環境変数（&lt;code&gt;ConnectionStrings__*&lt;/code&gt;）で透過的にオーバーライドする実践コードを習得する。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- 第2章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② パスワード平文コミットの恐怖 vs .env による安全管理（パラダイムシフト）&lt;/h2&gt;
    &lt;p&gt;
        まずは、なぜGit環境においてパスワードの取り扱いにこれほど神経を尖らせる必要があるのか、その本質的な理由を図解で確認しましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1-XsPinnHSoOULiQkBEvnp_hnpmBxdwSd&quot; alt=&quot;パスワード平文コミットの危険性 vs .env 安全管理&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】パスワード平文コミットの恐怖 vs .env による安全管理（Git履歴に残る漏洩事故と環境変数分離の安全性）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;Gitコミット履歴の「不変性」という罠&lt;/h3&gt;
    &lt;p&gt;
        「もし間違えてパスワードをコミットしても、すぐにファイルからパスワードを消して、もう一度コミット（修正コミット）すれば大丈夫なのでは？」&lt;br/&gt;
        これは初心者やGitに不慣れなエンジニアが最も陥りやすい&lt;strong&gt;致命的な誤解&lt;/strong&gt;です。
    &lt;/p&gt;
    &lt;p&gt;
        Gitは、すべてのコミット時点のスナップショットを暗号学的ハッシュ値（SHA-1/SHA-256）で厳密にチェーン化して保持する分散バージョン管理システムです。&lt;br/&gt;
        最新の &lt;code&gt;HEAD&lt;/code&gt; コミットでファイル内のパスワードを削除しても、&lt;strong&gt;過去のコミット履歴（&lt;code&gt;git log&lt;/code&gt; や &lt;code&gt;git show&lt;/code&gt;）を開けば、過去にプッシュされたファイルの内容は1文字の狂いもなく閲覧・復元可能&lt;/strong&gt;です。
    &lt;/p&gt;
    &lt;p&gt;
        現代のGitHubやGitLabには、リポジトリにプッシュされたコードを自動スキャンしてパスワードやAPIトークンを検知する「Secret Scanning」機能が備わっています。&lt;br/&gt;
        パブリックリポジトリに誤ってコミットした場合、&lt;strong&gt;数秒以内に世界中の自動クローラーに拾われ、悪用されてしまう&lt;/strong&gt;のが今のサイバーセキュリティの過酷な現実です。
    &lt;/p&gt;

    &lt;!-- 対比テーブル --&gt;
    &lt;div style=&quot;overflow-x: auto; margin: 30px 0;&quot;&gt;
        &lt;table style=&quot;width: 100%; border-collapse: collapse; font-size: 15px; text-align: left;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background: #0f172a; color: #ffffff;&quot;&gt;
                    &lt;th style=&quot;padding: 12px 16px; border: 1px solid #334155; width: 22%;&quot;&gt;比較項目&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 16px; border: 1px solid #334155; width: 39%; background: #991b1b;&quot;&gt;❌ 危険: 平文ベタ書き＆コミット&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px 16px; border: 1px solid #334155; width: 39%; background: #166534;&quot;&gt;⭕ 安全: .env による環境分離&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; font-weight: bold;&quot;&gt;パスワードの所在&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; color: #b91c1c;&quot;&gt;YAMLやコード内に直接ハードコード&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; color: #15803d; font-weight: bold;&quot;&gt;ローカル端末の &lt;code&gt;.env&lt;/code&gt; ファイル内のみ&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; font-weight: bold;&quot;&gt;Gitリポジトリ共有&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; color: #b91c1c;&quot;&gt;パスワードごと全員・全履歴に共有（危険）&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; color: #15803d;&quot;&gt;プレースホルダー（&lt;code&gt;${変数}&lt;/code&gt;）のみ共有（安全）&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; font-weight: bold;&quot;&gt;環境ごとの切り替え&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; color: #b91c1c;&quot;&gt;開発/本番でファイルを書き換え事故多発&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; color: #15803d;&quot;&gt;環境ごとの &lt;code&gt;.env&lt;/code&gt; を差し替えるだけで完結&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; font-weight: bold;&quot;&gt;漏洩時の影響&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; color: #b91c1c;&quot;&gt;全リポジトリ閲覧者・Git履歴から永続漏洩&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px 16px; border: 1px solid #e2e8f0; color: #15803d;&quot;&gt;ローカル漏洩なし（Git上に実値が一切存在しない）&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;!-- 第3章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ Gitコミット対象 vs .gitignore 除外の徹底分類&lt;/h2&gt;
    &lt;p&gt;
        では、マルチコンテナ連携プロジェクトにおいて、&lt;strong&gt;「何をGitで共有し、何を各自のPC内に隔離すべきなのか」&lt;/strong&gt;、その境界線を明確に定義しましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1e8kL9-XULeOs3uBIDm-qhzdW60I-2Vds&quot; alt=&quot;Gitコミット対象 vs .gitignore 除外の徹底分類&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】Gitコミット対象（共有） vs .gitignore 除外（秘匿）の徹底分類カード（.env.example 運用の真髄）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;1. Gitコミットすべきファイル（チームの設計図）&lt;/h3&gt;
    &lt;ul style=&quot;padding-left: 20px; line-height: 1.85;&quot;&gt;
        &lt;li&gt;
            &lt;strong&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/strong&gt; 
            複数コンテナの構成、ポートマッピング、ボリューム定義、サービス依存関係（&lt;code&gt;depends_on&lt;/code&gt;）などのアーキテクチャ設計図です。パスワード値そのものは書かず、後述する &lt;code&gt;${SA_PASSWORD}&lt;/code&gt; 形式の環境変数参照で記述し、全員で共有します。
        &lt;/li&gt;
        &lt;li&gt;
            &lt;strong&gt;&lt;code&gt;.env.example&lt;/code&gt;（超重要！運用の要）:&lt;/strong&gt; 
            本物のパスワードではなく、&lt;strong&gt;「このプロジェクトを動かすためにどんなキー名の環境変数が必要か」&lt;/strong&gt;を示したひな型（テンプレート）ファイルです。&lt;br/&gt;
            値には &lt;code&gt;YourStrongPasswordHere!&lt;/code&gt; や &lt;code&gt;localhost:1433&lt;/code&gt; といったダミー値・説明用サンプル値を記述してGit管理します。
        &lt;/li&gt;
        &lt;li&gt;
            &lt;strong&gt;&lt;code&gt;Dockerfile&lt;/code&gt; / &lt;code&gt;.dockerignore&lt;/code&gt; / ソースコード:&lt;/strong&gt; 
            当然ながらGit管理対象です。
        &lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;2. 絶対にGitコミットしてはいけないファイル（秘匿情報）&lt;/h3&gt;
    &lt;ul style=&quot;padding-left: 20px; line-height: 1.85;&quot;&gt;
        &lt;li&gt;
            &lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;（実値ファイル）:&lt;/strong&gt; 
            開発者個人のローカルパスワード、本番DBの管理者パスワード、クラウド接続文字列、外部API秘密鍵などの実値が記載されたファイルです。&lt;br/&gt;
            &lt;strong&gt;絶対に &lt;code&gt;.gitignore&lt;/code&gt; に追加し、Gitの追跡対象から完全に除外しなければなりません！&lt;/strong&gt;
        &lt;/li&gt;
        &lt;li&gt;
            &lt;strong&gt;&lt;code&gt;.env.local&lt;/code&gt; / &lt;code&gt;.env.production&lt;/code&gt;:&lt;/strong&gt; 
            特定環境用の実値ファイルも同様にGit除外対象です。
        &lt;/li&gt;
    &lt;/ul&gt;

    &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 20px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;margin-top: 0; color: #0f172a; font-size: 16px;&quot;&gt;📁 チーム開発における黄金のワークフロー&lt;/h4&gt;
        &lt;ol style=&quot;margin-bottom: 0; padding-left: 20px; line-height: 1.85; color: #334155;&quot;&gt;
            &lt;li&gt;プロジェクト作成者は &lt;code&gt;.env.example&lt;/code&gt; を作成してGitコミットする。&lt;/li&gt;
            &lt;li&gt;リポジトリルートの &lt;code&gt;.gitignore&lt;/code&gt; に &lt;code&gt;.env&lt;/code&gt; を忘れずに追記する。&lt;/li&gt;
            &lt;li&gt;新しい開発者が &lt;code&gt;git clone&lt;/code&gt; したら、まず &lt;code&gt;cp .env.example .env&lt;/code&gt;（Windowsなら &lt;code&gt;copy .env.example .env&lt;/code&gt;）を実行。&lt;/li&gt;
            &lt;li&gt;生成されたローカルの &lt;code&gt;.env&lt;/code&gt; に自分専用の開発パスワードを入力して &lt;code&gt;docker compose up -d&lt;/code&gt; を実行！&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;.gitignore の実践的な設定例&lt;/h3&gt;
    &lt;p&gt;プロジェクトのルートディレクトリにある &lt;code&gt;.gitignore&lt;/code&gt; には、以下のように記述を徹底します。&lt;/p&gt;

    &lt;pre style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-size: 14.5px; overflow-x: auto; line-height: 1.65;&quot;&gt;&lt;code&gt;# ==========================================
# 環境変数・機密設定ファイル（Git除外徹底）
# ==========================================
.env
.env.*
!.env.example

# ==========================================
# .NET / C# ビルド成果物・キャッシュ
# ==========================================
bin/
obj/
*.user
appsettings.Development.json
&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;font-size: 14.5px; color: #64748b; margin-top: 6px;&quot;&gt;
        💡 &lt;code&gt;.env.*&lt;/code&gt; で関連ファイルを一括除外した上で、&lt;code&gt;!.env.example&lt;/code&gt; でテンプレートファイルだけを明示的に除外解除（コミット対象化）するのがプロのベストプラクティスです。
    &lt;/p&gt;

    &lt;!-- 第4章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ Docker Compose の環境変数展開メカニズム&lt;/h2&gt;
    &lt;p&gt;
        それでは、&lt;code&gt;.env&lt;/code&gt; に定義した機密情報が、どのようにして &lt;code&gt;docker-compose.yml&lt;/code&gt; 経由でコンテナ内へ注入されるのか、その自動展開メカニズムを紐解いていきましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1iVrp--Oot96rKdrSE_BQYcCjdmkvk7Oz&quot; alt=&quot;Docker Compose の環境変数展開メカニズム&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】Docker Compose の環境変数展開メカニズム（.env 定義 ➡ ${VARIABLE} 展開 ➡ コンテナ注入の3ステップ）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;Composeの自動読み込み（Default .env File）仕様&lt;/h3&gt;
    &lt;p&gt;
        Docker Compose には非常に洗練されたビルトイン仕様が備わっています。&lt;br/&gt;
        &lt;code&gt;docker compose up&lt;/code&gt; コマンドを実行した作業ディレクトリに &lt;code&gt;.env&lt;/code&gt; という名前のファイルが存在する場合、Composeは&lt;strong&gt;コマンドライン引数で何も指定しなくても、自動的にその &lt;code&gt;.env&lt;/code&gt; ファイルを読み込んで内部の変数として展開&lt;/strong&gt;します。
    &lt;/p&gt;
    &lt;p&gt;
        YAMLファイル側では、&lt;code&gt;${変数名}&lt;/code&gt; というシンプルなプレースホルダー構文を記述しておくだけで、Composeが起動時に実値へと透過的に置換してくれるのです。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;実践コード比較：.env と .env.example&lt;/h3&gt;
    &lt;p&gt;まずは2つの環境変数ファイルの内容を比較してみましょう。&lt;/p&gt;

    &lt;div style=&quot;display: grid; grid-template-columns: 1fr; gap: 20px; margin: 20px 0;&quot;&gt;
        &lt;div&gt;
            &lt;div style=&quot;background: #334155; color: #ffffff; padding: 8px 16px; border-radius: 6px 6px 0 0; font-size: 14px; font-weight: bold;&quot;&gt;
                📄 .env.example（Gitコミットして共有するひな型）
            &lt;/div&gt;
            &lt;pre style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 0 0 6px 6px; font-size: 14px; overflow-x: auto; margin-top: 0; line-height: 1.65;&quot;&gt;&lt;code&gt;# ==========================================
# Docker Compose 共通環境変数テンプレート
# ※ 新規開発者はこのファイルをコピーして .env を作成してください
# ==========================================

# SQL Server 設定
DB_PASSWORD=YourStrongPasswordHere_123!
DB_PORT=1433

# Redis 設定
REDIS_PORT=6379

# ASP.NET Core 設定
ASPNETCORE_ENVIRONMENT=Development
API_HOST_PORT=8080
&lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;

        &lt;div&gt;
            &lt;div style=&quot;background: #0f766e; color: #ffffff; padding: 8px 16px; border-radius: 6px 6px 0 0; font-size: 14px; font-weight: bold;&quot;&gt;
                🔒 .env（ローカルPCのみに保持し、.gitignoreで除外する実値）
            &lt;/div&gt;
            &lt;pre style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 0 0 6px 6px; font-size: 14px; overflow-x: auto; margin-top: 0; line-height: 1.65;&quot;&gt;&lt;code&gt;# ==========================================
# ローカル開発用 実値設定（Gitコミット絶対禁止）
# ==========================================

# SQL Server 設定（自分だけの安全なパスワード）
DB_PASSWORD=MySecr3t_P@ssw0rd_2026!
DB_PORT=1433

# Redis 設定
REDIS_PORT=6379

# ASP.NET Core 設定
ASPNETCORE_ENVIRONMENT=Development
API_HOST_PORT=8080
&lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;変数展開に対応した docker-compose.yml 完全版&lt;/h3&gt;
    &lt;p&gt;
        続いて、上記の環境変数を安全に参照する &lt;code&gt;docker-compose.yml&lt;/code&gt; の記述です。パスワードが完全に変数化されている点に注目してください。
    &lt;/p&gt;

    &lt;pre style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-size: 14.5px; overflow-x: auto; line-height: 1.65;&quot;&gt;&lt;code&gt;version: &#39;3.8&#39;

services:
  # 1. SQL Server データベース
  db:
    image: mcr.microsoft.com/mssql/server:2022-latest
    container_name: sql_server_day24
    environment:
      ACCEPT_EULA: &quot;Y&quot;
      # .env からパスワードを安全に置換・注入
      MSSQL_SA_PASSWORD: &quot;${DB_PASSWORD}&quot;
    ports:
      - &quot;${DB_PORT}:1433&quot;
    volumes:
      - mssqldata:/var/opt/mssql
    healthcheck:
      test: [&quot;CMD-SHELL&quot;, &quot;/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P &quot;$${MSSQL_SA_PASSWORD}&quot; -C -Q &#39;SELECT 1&#39; || exit 1&quot;]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 15s

  # 2. Redis 高速キャッシュ
  redis:
    image: redis:7-alpine
    container_name: redis_day24
    ports:
      - &quot;${REDIS_PORT}:6379&quot;
    volumes:
      - redisdata:/data

  # 3. ASP.NET Core Web API
  api:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: web_api_day24
    environment:
      - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT}
      # C# の IConfiguration に合わせて接続文字列を環境変数でオーバーライド
      - ConnectionStrings__DefaultConnection=Server=db,1433;Database=DockerDemoDb;User Id=sa;Password=${DB_PASSWORD};TrustServerCertificate=True;
      - ConnectionStrings__Redis=redis:6379
    ports:
      - &quot;${API_HOST_PORT}:8080&quot;
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

volumes:
  mssqldata:
  redisdata:
&lt;/code&gt;&lt;/pre&gt;

    &lt;div style=&quot;background: #eff6ff; border-left: 4px solid #3b82f6; padding: 14px 18px; margin: 20px 0; font-size: 15px; color: #1e40af;&quot;&gt;
        &lt;strong&gt;💡 YAML内の &lt;code&gt;$${MSSQL_SA_PASSWORD}&lt;/code&gt; について:&lt;/strong&gt;&lt;br/&gt;
        Docker Composeでは、&lt;code&gt;${VARIABLE}&lt;/code&gt; は「Compose自体の変数展開」として解釈されます。一方、コンテナ内のシェルスクリプトにそのままドル記号を渡したい場合は、&lt;code&gt;$$&lt;/code&gt; と2つ重ねて記述（エスケープ）します。healthcheckコマンド内でコンテナ内環境変数を参照する際の必須テクニックです！
    &lt;/div&gt;

    &lt;!-- 第5章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ C# ASP.NET Core でのセキュアな設定注入（IConfiguration連携）&lt;/h2&gt;
    &lt;p&gt;
        Docker側でパスワードを変数化できても、C#アプリケーション側が機密情報をハードコードしていたら意味がありません。&lt;br/&gt;
        .NETの極めて強力な設定管理システム&lt;strong&gt;「&lt;code&gt;IConfiguration&lt;/code&gt;（構成プロバイダー）」&lt;/strong&gt;とDockerの連携パターンを確認しましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1JwFcovCK69fCRcOxf192lRoM_11ghAD7&quot; alt=&quot;C#（IConfiguration）へのセキュア設定注入&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】C#（IConfiguration）へのセキュア設定注入フロー（appsettings.json を環境変数で上書きする3ステップ）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;.NETの階層キーと「二重アンダースコア（__）」ルール&lt;/h3&gt;
    &lt;p&gt;
        ASP.NET Coreの &lt;code&gt;appsettings.json&lt;/code&gt; では、設定値は階層構造（JSONオブジェクト）で管理されます。
    &lt;/p&gt;

    &lt;pre style=&quot;background: #1e293b; color: #f8fafc; padding: 16px 20px; border-radius: 6px; font-size: 14px; overflow-x: auto; line-height: 1.65;&quot;&gt;&lt;code&gt;{
  &quot;ConnectionStrings&quot;: {
    &quot;DefaultConnection&quot;: &quot;Server=localhost;Database=Demo;User Id=sa;Password=dummy;&quot;,
    &quot;Redis&quot;: &quot;localhost:6379&quot;
  },
  &quot;Logging&quot;: {
    &quot;LogLevel&quot;: {
      &quot;Default&quot;: &quot;Information&quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;
        この &lt;code&gt;appsettings.json&lt;/code&gt; はGitコミットされます。そのため、パスワード部分にはダミー文字列やローカル開発用の仮の値を記載しておきます。&lt;br/&gt;
        そして、Docker Composeでコンテナを起動する際、環境変数として&lt;strong&gt;「&lt;code&gt;ConnectionStrings__DefaultConnection&lt;/code&gt;」&lt;/strong&gt;を渡します。
    &lt;/p&gt;
    &lt;p&gt;
        .NETの構成システムは、&lt;strong&gt;環境変数名に含まれる二重アンダースコア（&lt;code&gt;__&lt;/code&gt;）を、JSON階層のコロン（&lt;code&gt;:&lt;/code&gt;）へと自動的にマッピングして解釈&lt;/strong&gt;します。&lt;br/&gt;
        さらに、.NETのデフォルトの読み込み優先順位では&lt;strong&gt;「環境変数が &lt;code&gt;appsettings.json&lt;/code&gt; を無条件で上書き（オーバーライド）」&lt;/strong&gt;するため、コードを1行も変えることなく、コンテナ外から安全に本物の接続文字列を注入できるのです！
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e293b; margin-top: 30px; font-size: 19px; border-left: 4px solid #0db7ed; padding-left: 12px;&quot;&gt;Program.cs での透過的な接続文字列取得コード&lt;/h3&gt;
    &lt;p&gt;
        C#アプリケーション側は、値が &lt;code&gt;appsettings.json&lt;/code&gt; から来たのか、Dockerの環境変数から上書き注入されたのかを意識する必要は一切ありません。&lt;br/&gt;
        標準の &lt;code&gt;GetConnectionString&lt;/code&gt; メソッドを呼ぶだけで、完全にセキュアに取得できます。
    &lt;/p&gt;

    &lt;pre style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 20px; border-radius: 8px; font-size: 14.5px; overflow-x: auto; line-height: 1.65;&quot;&gt;&lt;code&gt;using Microsoft.EntityFrameworkCore;
using StackExchange.Redis;

var builder = WebApplication.CreateBuilder(args);

// ============================================================
// 1. 接続文字列の取得（環境変数が自動でオーバーライド適用済み）
// ============================================================
var dbConnectionString = builder.Configuration.GetConnectionString(&quot;DefaultConnection&quot;);
if (string.IsNullOrEmpty(dbConnectionString))
{
    throw exciting InvalidOperationException(&quot;DefaultConnection 接続文字列が設定されていません。.env を確認してください。&quot;);
}

var redisConnectionString = builder.Configuration.GetConnectionString(&quot;Redis&quot;) ?? &quot;localhost:6379&quot;;

// ============================================================
// 2. サービス登録（EF Core &amp; 分散キャッシュ）
// ============================================================
builder.Services.AddControllers();

// SQL Server 登録
builder.Services.AddDbContext&lt;AppDbContext&gt;(options =&gt;
    options.UseSqlServer(dbConnectionString));

// Redis 分散キャッシュ登録
builder.Services.AddStackExchangeRedisCache(options =&gt;
{
    options.Configuration = redisConnectionString;
    options.InstanceName = &quot;DockerDemo_&quot;;
});

var app = builder.Build();

app.UseAuthorization();
app.MapControllers();

app.Run();
&lt;/code&gt;&lt;/pre&gt;

    &lt;!-- 第6章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ YouTube動画連動：霊夢と魔理沙の掛け合い解説&lt;/h2&gt;
    &lt;p&gt;
        動画講義での霊夢と魔理沙のトークセッションから、実務の核心に迫るハイライトシーンをお届けします！
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 8px; padding: 22px 24px; margin: 25px 0;&quot;&gt;
        &lt;div style=&quot;margin-bottom: 18px;&quot;&gt;
            &lt;strong style=&quot;color: #dc2626;&quot;&gt;霊夢：&lt;/strong&gt;「オンプレミスのIISサーバーを構築してた頃は、サーバーにリモートデスクトップで入って、手動でweb.configを開いてsaパスワードを打ち込んで保存してたのよね…その時のパスワードが書かれた構築手順書Excelが、共有ファイルサーバーに転がってたりして…」
        &lt;/div&gt;
        &lt;div style=&quot;margin-bottom: 18px;&quot;&gt;
            &lt;strong style=&quot;color: #2563eb;&quot;&gt;魔理沙：&lt;/strong&gt;「うわあああ！オンプレあるあるだが、セキュリティ監査で見つかったら即アウトなやつだな！しかもGitでIaCを始めると、その『手順書にパスワードを書く感覚』でYAMLにベタ書きしてGitプッシュしちゃう事故が本当に多発するんだぜ。」
        &lt;/div&gt;
        &lt;div style=&quot;margin-bottom: 18px;&quot;&gt;
            &lt;strong style=&quot;color: #dc2626;&quot;&gt;霊夢：&lt;/strong&gt;「でも、.env.example というひな型だけをGitで共有して、本物の値が入った .env は .gitignore で絶対に外に出さないルールを徹底すれば、Gitリポジトリを社内外に安全に公開できるのね！」
        &lt;/div&gt;
        &lt;div style=&quot;margin-bottom: 0;&quot;&gt;
            &lt;strong style=&quot;color: #2563eb;&quot;&gt;魔理沙：&lt;/strong&gt;「その通りだ！さらにC#側も二重アンダースコア（&lt;code&gt;ConnectionStrings__DefaultConnection&lt;/code&gt;）による透過的な環境変数オーバーライドを使えば、コードは完全に無菌状態（パスワードゼロ）を維持できる。これが現場のプロが実践する堅牢なコンテナセキュリティ設計だぜ！」
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 第7章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑦ 実務でありがちな落とし穴＆トラブルシューティング&lt;/h2&gt;

    &lt;div style=&quot;margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #b91c1c; font-size: 18px; margin-bottom: 8px;&quot;&gt;落とし穴①: .gitignore に書いたのに .env がコミット対象から消えない！&lt;/h3&gt;
        &lt;p style=&quot;margin-top: 4px;&quot;&gt;
            &lt;strong&gt;【現象】&lt;/strong&gt; &lt;code&gt;.gitignore&lt;/code&gt; に &lt;code&gt;.env&lt;/code&gt; と追記したのに、&lt;code&gt;git status&lt;/code&gt; を叩くと &lt;code&gt;modified: .env&lt;/code&gt; と表示され、Gitが追跡を止めない。
        &lt;/p&gt;
        &lt;div style=&quot;background: #fef2f2; border-left: 4px solid #ef4444; padding: 12px 16px; margin: 10px 0; font-size: 15px; color: #991b1b;&quot;&gt;
            &lt;strong&gt;原因と対策:&lt;/strong&gt;&lt;br/&gt;
            &lt;code&gt;.gitignore&lt;/code&gt; は&lt;strong&gt;「まだ一度もGitに追跡（インデックス登録）されていない新規ファイル」&lt;/strong&gt;にのみ効果を発揮します。過去に一度でも &lt;code&gt;git add .env&lt;/code&gt; を実行してしまった場合、Gitのキャッシュに残っているため除外されません。&lt;br/&gt;
            以下のコマンドでGitの追跡インデックスからのみ削除（ローカルの実ファイルは維持）してください。
            &lt;pre style=&quot;background: #1e293b; color: #f8fafc; padding: 10px 14px; border-radius: 4px; margin: 8px 0; font-size: 13.5px;&quot;&gt;&lt;code&gt;git rm --cached .env
git commit -m &quot;fix: .env をGit追跡から完全に除外&quot;&lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div style=&quot;margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #b91c1c; font-size: 18px; margin-bottom: 8px;&quot;&gt;落とし穴②: パスワードに特殊記号（$ や #）が含まれていて展開が壊れる&lt;/h3&gt;
        &lt;p style=&quot;margin-top: 4px;&quot;&gt;
            &lt;strong&gt;【現象】&lt;/strong&gt; &lt;code&gt;DB_PASSWORD=P@ss$$word#1&lt;/code&gt; のように、パスワードにドル記号（&lt;code&gt;$&lt;/code&gt;）やシャープ（&lt;code&gt;#&lt;/code&gt;）が含まれていると、Docker Composeが別の環境変数として誤認識したり、&lt;code&gt;#&lt;/code&gt; 以降がコメントとして切り捨てられて認証エラーになる。
        &lt;/p&gt;
        &lt;div style=&quot;background: #fef2f2; border-left: 4px solid #ef4444; padding: 12px 16px; margin: 10px 0; font-size: 15px; color: #991b1b;&quot;&gt;
            &lt;strong&gt;原因と対策:&lt;/strong&gt;&lt;br/&gt;
            &lt;code&gt;.env&lt;/code&gt; ファイル内では、特殊記号を含む値はダブルクォートで囲むのが安全です。&lt;br/&gt;
            また、Compose YAMLファイル内でドル記号をリテラルとして扱いたい場合は &lt;code&gt;$$&lt;/code&gt; とエスケープしてください。
            &lt;pre style=&quot;background: #1e293b; color: #f8fafc; padding: 10px 14px; border-radius: 4px; margin: 8px 0; font-size: 13.5px;&quot;&gt;&lt;code&gt;# .env 内
DB_PASSWORD=&quot;MyStr0ng#P@ssword!&quot;&lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div style=&quot;margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #b91c1c; font-size: 18px; margin-bottom: 8px;&quot;&gt;落とし穴③: CI/CD（GitHub Actions等）での環境変数注入はどうする？&lt;/h3&gt;
        &lt;p style=&quot;margin-top: 4px;&quot;&gt;
            &lt;strong&gt;【疑問】&lt;/strong&gt; &lt;code&gt;.env&lt;/code&gt; をGitコミットしない場合、GitHub Actions などの自動テストやビルドパイプラインではどうやって環境変数を渡すのか？
        &lt;/p&gt;
        &lt;div style=&quot;background: #eff6ff; border-left: 4px solid #3b82f6; padding: 12px 16px; margin: 10px 0; font-size: 15px; color: #1e40af;&quot;&gt;
            &lt;strong&gt;プロの解決策:&lt;/strong&gt;&lt;br/&gt;
            GitHubリポジトリの設定（Settings ➡ Secrets and variables ➡ Actions）に &lt;code&gt;DB_PASSWORD&lt;/code&gt; をシークレットとして登録します。&lt;br/&gt;
            ワークフローYAML側で、&lt;code&gt;env: DB_PASSWORD: ${{ secrets.DB_PASSWORD }}&lt;/code&gt; と指定して &lt;code&gt;docker compose up -d&lt;/code&gt; を実行すれば、Composeが自動でシェル環境変数を最優先展開して起動してくれます！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 第8章 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑧ 本日のまとめ・理解したい最重要ポイント&lt;/h2&gt;

    &lt;div style=&quot;background: #f0fdf4; border: 2px solid #86efac; border-radius: 8px; padding: 22px 24px; margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;color: #166534; margin-top: 0; margin-bottom: 14px; font-size: 18px;&quot;&gt;🎉 Day 24 の最重要エッセンス（復習）&lt;/h3&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; line-height: 1.85; color: #14532d;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;Gitの履歴にパスワードを残さない:&lt;/strong&gt; YAMLやコードに機密情報を直接書くのは厳禁。修正コミットを打っても過去ログから流出する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;.env.example と .env の役割分担:&lt;/strong&gt; キー一覧とダミー値のテンプレート（&lt;code&gt;.env.example&lt;/code&gt;）だけをGit管理し、本物の値が入った &lt;code&gt;.env&lt;/code&gt; は &lt;code&gt;.gitignore&lt;/code&gt; で完全隔離する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Docker Compose の自動展開:&lt;/strong&gt; カレントディレクトリの &lt;code&gt;.env&lt;/code&gt; をComposeが自動検出し、&lt;code&gt;${VARIABLE}&lt;/code&gt; に置換してコンテナへ注入する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;C#（IConfiguration）の階層マッピング:&lt;/strong&gt; &lt;code&gt;ConnectionStrings__DefaultConnection&lt;/code&gt; のように二重アンダースコアで環境変数を渡すことで、コード無修正のままセキュアに接続文字列を上書きできる。&lt;/li&gt;
        &lt;/ul&gt;
        &lt;div style=&quot;margin-top: 15px; padding-top: 12px; border-top: 1px dashed #86efac; font-size: 15px; color: #14532d;&quot;&gt;
            &lt;strong&gt;次回【Day 25】予告:&lt;/strong&gt;&lt;br/&gt;
            『コンテナのデータ永続化（Named Volume vs Bind Mount）の決定版』〜コンテナ破棄でもDBデータが絶対に消えないストレージ設計の真髄〜
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/5169000669903106835/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-24docker-composeyml-git-env-git-c.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/5169000669903106835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/5169000669903106835'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-24docker-composeyml-git-env-git-c.html' title='【Day 24】docker-compose.yml のGit共有と .env のGit除外ルール 〜パスワード・接続文字列の漏洩を防ぐ安全なチーム開発とC#環境変数注入設計〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1GJFvmbK3x8WV6R1wk8CbpCrsAWOPYWmk=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-7994228893693980474</id><published>2026-10-19T18:09:56.439+09:00</published><updated>2026-10-19T18:09:56.439+09:00</updated><title type='text'>【Day 21】【Case 1】新規開発フェーズ（複数人でのスプリント並行開発）</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1cpnXma4NrHsNu8yrv-xYNUVT0UZgKkPb&quot; alt=&quot;Day 21 アイキャッチ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【Day 21】スプリント開発を支えるGit並行開発フロー&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回までの第4部では、ブランチ戦略、命名規約、コミットメッセージ、そしてプッシュ前チェックリストといった「現場の実践ルール」を徹底的に叩き込んできました。&lt;br/&gt;
            そして本日のDay 21より、いよいよ本講座のクライマックスである&lt;strong&gt;【第5部: 開発フェーズ別・現場ケーススタディ】&lt;/strong&gt;が開幕します！&lt;br/&gt;
            記念すべきCase 1のテーマは、現場で最も日常的かつダイナミックな&lt;strong&gt;「新規開発フェーズ（複数人でのスプリント並行開発）」&lt;/strong&gt;です！&lt;br/&gt;
            「来週のリリースに向けて、3人のC#エンジニアが同時に認証機能・決済機能・管理画面を開発する」——そんなリアルな現場を舞台にシミュレーションを行います。&lt;br/&gt;
            Subversion (SVN) や Visual SourceSafe (VSS) で開発してきたベテランの方なら、「複数人で同じプロジェクトを触ると、誰かがコミットした瞬間コンパイルエラーになり、一日中ビルド修復で終わってしまった…」というトラウマを一度は経験したことがあるはずです。&lt;br/&gt;
            しかし、Gitを正しく使いこなせば、誰一人として他人の作業に邪魔されることなく、最高速度で並行開発を進めることができます。&lt;br/&gt;
            本日は、トピックブランチによる完全隔離、C#マルチレイヤー構成での競合回避術、そしてプロが毎朝欠かさず行う「リベース習慣」とPR作成までの完全フローを完全解説します！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        アジャイルやスクラム開発における「スプリント（1〜2週間の開発サイクル）」では、チーム全員が複数の異なるタスクを並行して実装します。&lt;br/&gt;
        このとき、バージョン管理システムが「中央集権の一本道」であるか、「分散型の自律ブランチ」であるかによって、開発効率とエンジニアの心理的安全性には天と地ほどの差が生まれます。&lt;br/&gt;
        Gitのトピックブランチモデルを導入することで、開発者は「自分の城」の中で自由に試行錯誤し、完成した機能だけを厳格なレビューとCIテストを経て本流へ合流させることが可能になります。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;SVNの一本道コミット地獄とGitのトピックブランチ隔離の決定的な違いを理解する&lt;/li&gt;
            &lt;li&gt;3人のC#エンジニアが並行開発する現場シナリオ（認証・決済・管理画面）の全体像を把握する&lt;/li&gt;
            &lt;li&gt;C#マルチレイヤー構成（API・Domain・UI）における競合を最小化するプロジェクト設計を身につける&lt;/li&gt;
            &lt;li&gt;毎朝のルーティン：&lt;code&gt;git fetch&lt;/code&gt; と &lt;code&gt;git rebase origin/develop&lt;/code&gt; による競合の超早期解消をマスターする&lt;/li&gt;
            &lt;li&gt;プッシュからPull Request（PR）起票、CI通過、レビュー、マージまでの黄金サイクルを実践できる&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: SVN地獄 vs Gitブランチ隔離 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】スプリント開発の安全性対比：SVN地獄 vs Gitの完全隔離&lt;/h2&gt;
    &lt;p&gt;
        まずは、SVNのような集中型バージョン管理とGitにおける「複数人並行開発」の構造的な違いを図解で比較してみましょう。
    &lt;/p&gt;

    &lt;!-- 図解①: SVN vs Git --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1eXnRBlMcU2loV5E2Y6V5060Tsm_5Qn2S&quot; alt=&quot;スプリント開発の安全性対比&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】SVNのコミット地獄 vs Gitのトピックブランチ完全隔離&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;一本道への直接コミット vs 自律的なトピックブランチ&lt;/h3&gt;
    &lt;ul style=&quot;line-height: 1.95; padding-left: 25px;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;SVNの悲劇（一本道の中央共有）&lt;/strong&gt;: SVNではブランチの作成やマージが重厚で難しいため、開発者全員が同じ &lt;code&gt;trunk&lt;/code&gt;（または単一ブランチ）に対して直接コミットしがちでした。その結果、「Aさんが作りかけのクラスをコミットしたせいで、BさんのPCでコンパイルが通らなくなる」「誰かのバグのせいでチーム全体の作業が丸一日ストップする」という地獄が日常茶飯事でした。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Gitの理想（トピックブランチによる完全隔離）&lt;/strong&gt;: Gitではブランチの作成・切り替えが一瞬です。開発者は必ずタスクごとの「トピックブランチ（例: &lt;code&gt;feature/auth-jwt&lt;/code&gt;）」を作成して作業します。自分のブランチの中でコードがどれほど未完成でも、テストが落ちていても、&lt;strong&gt;他のメンバーの開発環境には1ミリも影響を与えません&lt;/strong&gt;。&lt;/li&gt;
    &lt;/ul&gt;

    &lt;!-- セクション③: 3人の並行開発シミュレーション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【現場シミュレーション】3人のC#エンジニアによるスプリント並行開発&lt;/h2&gt;
    &lt;p&gt;
        それでは、具体的な現場シナリオを見ていきましょう。&lt;br/&gt;
        ECサイトの新規機能追加スプリントにおいて、3人のC#エンジニア（Aさん、Bさん、Cさん）が同一のC#ソリューション（&lt;code&gt;ECommerce.sln&lt;/code&gt;）に対して並行開発を行います。
    &lt;/p&gt;

    &lt;!-- 図解②: 3人の並行開発構成図 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1rO8IElYXDgw6K-kVr8zYUOlysRYHWflQ&quot; alt=&quot;3人の並行開発シミュレーション&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】C#マルチレイヤー構成における3人の独立並行開発フロー&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;チームメンバーのタスクとブランチ一覧&lt;/h3&gt;
    &lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0; font-size: 15.5px;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background: #1e3a8a; color: white;&quot;&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1; width: 15%;&quot;&gt;担当者&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1; width: 30%;&quot;&gt;開発タスク&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1; width: 25%;&quot;&gt;作業ブランチ名&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1;&quot;&gt;主な変更レイヤー&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;strong&gt;Aさん（リード）&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;JWTによるユーザー認証API実装&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;feature/auth-jwt&lt;/code&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;ECommerce.Api/Controllers&lt;/code&gt;&lt;br/&gt;&lt;code&gt;ECommerce.Infrastructure/Auth&lt;/code&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;strong&gt;Bさん（バックエンド）&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;Stripe決済連携とドメインロジック&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;feature/payment-stripe&lt;/code&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;ECommerce.Domain/Payment&lt;/code&gt;&lt;br/&gt;&lt;code&gt;ECommerce.Services/Payment&lt;/code&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;strong&gt;Cさん（フロントエンド）&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;売上集計・ユーザー管理ダッシュボード&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;feature/admin-dashboard&lt;/code&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;ECommerce.Web/Components&lt;/code&gt;&lt;br/&gt;&lt;code&gt;ECommerce.Web/Pages&lt;/code&gt;&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;div style=&quot;background: #eff6ff; border-left: 5px solid #2563eb; padding: 18px 20px; margin: 25px 0; border-radius: 6px;&quot;&gt;
        &lt;strong style=&quot;color: #1e40af; font-size: 16.5px;&quot;&gt;💡 C#現場の知恵：コンフリクトを激減させる「レイヤー分割とインターフェース」&lt;/strong&gt;&lt;br/&gt;
        &lt;p style=&quot;margin: 8px 0 0 0; line-height: 1.85;&quot;&gt;
            C#で複数人が同じソリューションを開発する場合、&lt;strong&gt;「プロジェクト分割（マルチレイヤー構成）」&lt;/strong&gt;と&lt;strong&gt;「インターフェースによる境界定義」&lt;/strong&gt;を徹底することで、ファイルの物理的競合（コンフリクト）を劇的に減らすことができます。&lt;br/&gt;
            例えば、Bさんが決済ロジックを作る際、Aさんの認証やCさんのUIが未完成でも、&lt;code&gt;IPaymentService&lt;/code&gt; インターフェースさえ合意していれば、お互いのコードを1行も触ることなく完全に並行して単体テストまで書き上げることができるのです。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- セクション④: 毎日のリベース習慣 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【プロの朝習慣】毎朝のルーティン：最新developのリベース取り込み&lt;/h2&gt;
    &lt;p&gt;
        「スプリント開発の最大の敵」は何でしょうか？&lt;br/&gt;
        それは、&lt;strong&gt;「長期間放置されて親ブランチ（develop）から乖離しすぎた巨大なブランチ」&lt;/strong&gt;です。&lt;br/&gt;
        スプリントの1週間、自分のブランチに引きこもって他のメンバーの変更を一度も取り込まずにいると、最終日にいざマージしようとした瞬間、数十箇所の衝突が発生し「マージ地獄」に陥ります。&lt;br/&gt;
        これを防ぐ唯一にして最強の習慣が、&lt;strong&gt;「毎朝のリベース（Daily Rebase）」&lt;/strong&gt;です！
    &lt;/p&gt;

    &lt;!-- 図解③: 毎日のリベースフロー --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1Dk6K7m7a5m3JVu0moIaKpVFZCZdo9iJf&quot; alt=&quot;毎日のリベース習慣&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】毎朝のルーティン：最新developの取り込みと競合の極小化&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;毎朝出社したら実行する「黄金の3ステップ」&lt;/h3&gt;
    &lt;p&gt;自分の作業を開始する前に、ターミナルで以下のコマンドを実行します。&lt;/p&gt;

    &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 20px 22px; border-radius: 8px; margin: 20px 0; font-family: &#39;Consolas&#39;, &#39;Courier New&#39;, monospace; font-size: 15px; line-height: 1.7; overflow-x: auto;&quot;&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 1. リモートの最新情報をすべて取得（手元のブランチは動かさない）&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; fetch origin&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 2. 自分のブランチの分岐元を最新の origin/develop に付け替える&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;git&lt;/span&gt; rebase origin/develop&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 3. ビルドとテストが正常に通ることを即座に確認！&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;dotnet&lt;/span&gt; build&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;dotnet&lt;/span&gt; test
    &lt;/div&gt;

    &lt;div style=&quot;background: #fdf2f8; border-left: 5px solid #db2777; padding: 18px 20px; margin: 25px 0; border-radius: 6px;&quot;&gt;
        &lt;strong style=&quot;color: #9d174d; font-size: 16.5px;&quot;&gt;⚠️ なぜ merge ではなく rebase を使うのか？&lt;/strong&gt;&lt;br/&gt;
        &lt;p style=&quot;margin: 8px 0 0 0; line-height: 1.85;&quot;&gt;
            開発途中のブランチに対して &lt;code&gt;git merge develop&lt;/code&gt; を繰り返すと、「Merge branch &#39;develop&#39; into feature/xxx」という無意味な合流コミットが大量に発生し、コミット履歴がクモの巣のように汚れてしまいます。&lt;br/&gt;
            &lt;code&gt;git rebase origin/develop&lt;/code&gt; を使えば、&lt;strong&gt;「あたかも最新のdevelopから今さっきブランチを切って開発を始めたかのような、一直線で美しい履歴」&lt;/strong&gt;を維持できます。&lt;br/&gt;
            万が一コンフリクトが発生しても、昨日の1日分だけの小さな差分なので、数分で安全に解消できるのです。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑤: PR作成からマージ完了までの完全フロー --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【品質担保】PR作成からCI自動テスト・レビュー・マージまでの完全フロー&lt;/h2&gt;
    &lt;p&gt;
        機能の実装が完了したら、いよいよGitHub上で本流（&lt;code&gt;develop&lt;/code&gt;）へ統合するための「プルリクエスト（Pull Request: PR）」を作成します。&lt;br/&gt;
        プロの開発現場では、以下の4つのステップが厳格な品質ゲートとして機能しています。
    &lt;/p&gt;

    &lt;!-- 図解④: PR作成〜マージフロー --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1wZIYWHz8AVdFTt_1KLxYKxvhZmPKxMGZ&quot; alt=&quot;PR作成からマージ完了までの完全フロー&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】GitHub PR作成・CIテスト・ピアレビュー・マージの4ステップ&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;プルリクエスト成功の4大ステップ&lt;/h3&gt;
    &lt;ol style=&quot;line-height: 2.1; padding-left: 25px; margin: 18px 0;&quot;&gt;
        &lt;li&gt;
            &lt;strong&gt;① プッシュ＆PR起票&lt;/strong&gt;:&lt;br/&gt;
            Day 20で学んだ「5大セルフチェック」を済ませ、&lt;code&gt;git push -u origin feature/auth-jwt&lt;/code&gt; でリモートへプッシュ。GitHubでPRを作成します。&lt;br/&gt;
            PRの説明欄には「変更の目的」「実装概要」「確認手順」「関連チケット番号」を明記します。
        &lt;/li&gt;
        &lt;li&gt;
            &lt;strong&gt;② GitHub Actions（CI）による自動テスト&lt;/strong&gt;:&lt;br/&gt;
            PRが作成された瞬間、クラウド上のCIランナーが起動し、自動で &lt;code&gt;dotnet build&lt;/code&gt; と &lt;code&gt;dotnet test&lt;/code&gt; を実行します。&lt;br/&gt;
            1つでもテストが失敗するとマージボタンが赤くロックされ、壊れたコードが混入するのを機械的に遮断します。
        &lt;/li&gt;
        &lt;li&gt;
            &lt;strong&gt;③ チームメンバーによるピアレビュー&lt;/strong&gt;:&lt;br/&gt;
            他のメンバー（例: AさんのコードをBさんやテックリードがレビュー）が差分を確認し、設計の妥当性、可読性、エッジケースの考慮をチェックします。「LGTM (Looks Good To Me / 承認)」をもらうことで、チーム全員のコード品質が底上げされます。
        &lt;/li&gt;
        &lt;li&gt;
            &lt;strong&gt;④ developブランチへの統合（マージ完了）&lt;/strong&gt;:&lt;br/&gt;
            承認とCI通過が揃ったら、GitHubの「Squash and merge」または「Rebase and merge」を実行してdevelopブランチへ統合！&lt;br/&gt;
            不要になったトピックブランチは即座に削除し、ローカルも最新のdevelopへ同期して次のタスクへ進みます。
        &lt;/li&gt;
    &lt;/ol&gt;

    &lt;!-- セクション⑥: まとめと次回予告 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ 現場の実践まとめ＆次回予告&lt;/h2&gt;
    &lt;div style=&quot;background: #f8fafc; border: 2px solid #cbd5e1; border-radius: 8px; padding: 22px 24px; margin: 25px 0;&quot;&gt;
        &lt;h3 style=&quot;margin-top: 0; color: #1e3a8a; font-size: 19px;&quot;&gt;📌 本日の最重要ポイントまとめ&lt;/h3&gt;
        &lt;ul style=&quot;line-height: 1.95; padding-left: 22px; margin-bottom: 0;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;トピックブランチで隔離せよ&lt;/strong&gt;: SVNの一本道コミットとは決別し、タスクごとに独立したブランチで作業することでチームの足を引っ張らない。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;マルチレイヤーとインターフェース&lt;/strong&gt;: C#ソリューションではプロジェクト分割とインターフェース設計により、並行開発時の物理競合を根本から排除する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;毎朝のリベース習慣&lt;/strong&gt;: &lt;code&gt;git fetch origin&lt;/code&gt; と &lt;code&gt;git rebase origin/develop&lt;/code&gt; を毎朝実行し、差分を極小のうちに解消してマージ地獄を防ぐ。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;PR＋CI自動化が品質の盾&lt;/strong&gt;: プルリクエスト起票時にGitHub Actionsで &lt;code&gt;dotnet test&lt;/code&gt; を全件自動実行し、ALL GREENとピアレビューを経て安全にdevelopへ統合する。&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #f0fdf4; border-left: 5px solid #16a34a; padding: 18px 20px; margin: 30px 0; border-radius: 6px;&quot;&gt;
        &lt;strong style=&quot;color: #15803d; font-size: 17px;&quot;&gt;🚀 次回予告：Day 22&lt;/strong&gt;&lt;br/&gt;
        &lt;p style=&quot;margin: 8px 0 0 0; line-height: 1.85;&quot;&gt;
            次回は、第5部 ケーススタディの第2弾！&lt;br/&gt;
            &lt;strong&gt;【Day 22: 【Case 2】運用保守・障害対応フェーズ（hotfix緊急パッチとCherry-pick）】&lt;/strong&gt;をお届けします！&lt;br/&gt;
            本番環境で緊急バグが発覚したとき、開発中の未完成コードを巻き込まずに本番ブランチ（main）だけに修正を当て、さらにそれをdevelopブランチにも安全に同期させるプロの「hotfix＆チェリーピック運用術」を完全解説します。お楽しみに！
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/7994228893693980474/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-21case-1.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/7994228893693980474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/7994228893693980474'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-21case-1.html' title='【Day 21】【Case 1】新規開発フェーズ（複数人でのスプリント並行開発）'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1cpnXma4NrHsNu8yrv-xYNUVT0UZgKkPb=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-2338713073181922454</id><published>2026-10-19T09:20:52.194+09:00</published><updated>2026-10-19T09:20:52.194+09:00</updated><title type='text'>【Day 23】Redisキャッシュを追加した3層コンテナアーキテクチャ 〜Web API ＋ SQL Server ＋ Redis の分散キャッシュ・セッション管理をComposeで構築〜</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 840px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1QMMGvPSGKXtVtiEI58_ztEoAKmNYz4xd&quot; alt=&quot;Day 23 アイキャッチ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ Day 23: Redisキャッシュを追加した3層コンテナアーキテクチャ&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;!-- 講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f9ff; border-left: 6px solid #0db7ed; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;🐳&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #0c4a6e; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;受講生の皆さん、お疲れ様です！ Docker/コンテナ実践講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回【Day 22】では、C# ASP.NET Core Web API と Microsoft SQL Server という実務の王道2大サービスを、Docker Composeで美しく連携させる環境を構築しました。&lt;br/&gt;
            そして本日【Day 23】は、ここに超高速インメモリKVS（Key-Value Store）である&lt;strong&gt;「Redis」&lt;/strong&gt;を追加し、現代のエンタープライズWeb開発における標準形である&lt;strong&gt;「モダン3層コンテナアーキテクチャ」&lt;/strong&gt;へ進化させます！&lt;br/&gt;
            ミドルウェアが増えるたびにサーバー調達とセットアップ手順書に追われていた過去と決別し、YAMLの数行追加だけでハイパフォーマンスな分散キャッシュ環境を手に入れる快感をぜひ体験してください！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        「Web APIのレスポンスが遅い…原因を調べたら、同じマスタデータを何度もSQL Serverにクエリ発行していた」&lt;br/&gt;
        「キャッシュを導入したいが、オンプレミス環境でRedisサーバーを別に1台立てて設定するのは承認も構築も大変すぎる…」&lt;br/&gt;
        「C#の &lt;code&gt;IMemoryCache&lt;/code&gt; でローカルメモリにキャッシュしたら、コンテナをスケールアウト（複数台稼働）させた瞬間にデータ不整合が発生した…」
    &lt;/p&gt;
    &lt;p&gt;
        Webシステムの規模が拡大するにつれ、データベース（RDBMS）へのアクセス集中は必ずシステムのボトルネックになります。&lt;br/&gt;
        その特効薬となるのが&lt;strong&gt;「Redisによる分散キャッシュ」&lt;/strong&gt;ですが、従来はRedisサーバーの構築・管理コストの高さから導入を躊躇する現場も少なくありませんでした。&lt;br/&gt;
        しかし、Docker Composeを使えば、&lt;strong&gt;わずか数行のYAMLを追加するだけで本番同等のRedisコンテナが立ち上がり&lt;/strong&gt;、C#の &lt;code&gt;IDistributedCache&lt;/code&gt; を通じて極めてシンプルに分散キャッシュを実装できます！
    &lt;/p&gt;
    &lt;p&gt;
        本日の講義を修了すると、以下の3大目標を完全に達成できます。
    &lt;/p&gt;
    &lt;ul style=&quot;background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 20px 25px 20px 45px; margin: 20px 0; line-height: 1.9;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;モダン3層コンテナアーキテクチャ（Web API ＋ Redis ＋ SQL Server）&lt;/strong&gt;の役割分担と設計原則を完全に理解する。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;docker-compose.yml へのRedisサービス定義（ポート・ボリューム・内部DNS連携）&lt;/strong&gt;を記述し、1コマンドで3層環境を立ち上げられる。&lt;/li&gt;
        &lt;li&gt;ASP.NET Coreの標準インターフェースである &lt;strong&gt;&lt;code&gt;IDistributedCache&lt;/code&gt;（StackExchange.Redis）&lt;/strong&gt; を用いて、実務標準の&lt;strong&gt;「Cache-Aside パターン」&lt;/strong&gt;を堅牢に実装できる。&lt;/li&gt;
    &lt;/ul&gt;

    &lt;!-- 3層アーキテクチャの全貌 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② モダン3層コンテナアーキテクチャの全貌（パラダイムシフト）&lt;/h2&gt;
    &lt;p&gt;
        まずは、Web API、Redis、SQL Serverがどのように連携し、高速レスポンスと高い耐障害性を実現するのか、その全体アーキテクチャを図解で確認しましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1PnVhfmRl8o3D5Orp9qvEXznoQnThiljh&quot; alt=&quot;モダン3層コンテナアーキテクチャ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】モダン3層コンテナアーキテクチャ（Web API層 ➡ Redis分散キャッシュ層 ➡ SQL Server永続化層の役割分担）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;p&gt;
        この3層アーキテクチャでは、各コンテナが明確な単一責務を持っています。
    &lt;/p&gt;
    &lt;ul style=&quot;line-height: 1.8; margin-bottom: 20px;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;① Web API層（ASP.NET Core）:&lt;/strong&gt; クライアントからのHTTPリクエストを処理し、ビジネスロジックを実行するアプリケーション層。ステートレス（無状態）に設計され、負荷に応じて何台でも水平スケールアウト可能です。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;② Redis分散キャッシュ層:&lt;/strong&gt; すべてのデータをメモリ上で保持する超高速KVS。頻繁に参照されるマスタデータやユーザーセッション情報をミリ秒未満（サブミリ秒）で即座に返却し、後段のRDBMSを守る盾となります。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;③ SQL Server永続化層:&lt;/strong&gt; トランザクション整合性（ACID特性）を保証するリレーショナルデータベース。ディスク上のボリューム（Volume）にデータを安全に永続化します。&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3 style=&quot;color: #c2410c; font-size: 19px; margin-top: 25px; margin-bottom: 12px;&quot;&gt;VM/物理サーバー時代との決定的な違い：セットアップ手順書の消滅&lt;/h3&gt;
    &lt;p&gt;
        従来のオンプレミスや仮想マシン（VM）運用では、システムに「Redis」という新しいミドルウェアを追加するだけで、以下のような膨大な作業が発生していました。
    &lt;/p&gt;
    &lt;ul style=&quot;line-height: 1.8; margin-bottom: 20px;&quot;&gt;
        &lt;li&gt;新規Linuxサーバーの調達・OSインストール・IPアドレス割り当て申請&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;yum&lt;/code&gt; や &lt;code&gt;apt&lt;/code&gt; によるRedisパッケージのインストールと依存関係解決&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;/etc/redis/redis.conf&lt;/code&gt; の手動パラメータ調整（bind設定、protected-mode、メモリ上限設定など）&lt;/li&gt;
        &lt;li&gt;ホストPCや開発者ごとのファイアウォール開放設定と疎通確認&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;
        これがDocker Composeになると、&lt;strong&gt;「公式の &lt;code&gt;redis:7-alpine&lt;/code&gt; イメージをYAMLに数行書くだけ」&lt;/strong&gt;で完結します。&lt;br/&gt;
        チームの全員が、新人のPCであってもCIサーバーであっても、&lt;code&gt;docker compose up -d&lt;/code&gt; を打つだけで寸分違わぬ同一構成のRedisキャッシュ環境が5秒で立ち上がります。インフラ構成の変更が、Gitのプルリクエスト上でたった数行の差分としてレビュー可能になるのです！
    &lt;/p&gt;

    &lt;!-- docker-compose.yml へのRedis追加 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ docker-compose.yml へのRedisサービス完全定義&lt;/h2&gt;
    &lt;p&gt;
        それでは、前回作成した &lt;code&gt;docker-compose.yml&lt;/code&gt; に Redis サービスを追加した完全版コードを見てみましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1C7lh00YR0fVaayPsab0L9ZElD1tA0ydH&quot; alt=&quot;docker-compose.yml へのRedis追加&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】docker-compose.yml へのRedisサービス追加とWeb API接続定義（内部DNSと環境変数注入）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 22px 24px; margin: 25px 0; font-family: Consolas, Monaco, monospace; font-size: 14.5px; overflow-x: auto; line-height: 1.75;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# docker-compose.yml（Web API + SQL Server + Redis 3層連携）&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #38bdf8;&quot;&gt;services:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f472b6;&quot;&gt;db:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;image:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;mcr.microsoft.com/mssql/server:2022-latest&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;container_name:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;my-sqlserver&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;environment:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #4ade80;&quot;&gt;ACCEPT_EULA=Y&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #4ade80;&quot;&gt;MSSQL_SA_PASSWORD=YourStrong@Pass123&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;ports:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;1433:1433&quot;&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;volumes:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #fcd34d;&quot;&gt;sqldata:/var/opt/mssql&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;healthcheck:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;test:&lt;/span&gt; [&lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;CMD-SHELL&quot;&lt;/span&gt;, &lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P &#39;YourStrong@Pass123&#39; -C -Q &#39;SELECT 1&#39; || exit 1&quot;&lt;/span&gt;]&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;interval:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;10s&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;timeout:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;5s&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;retries:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;5&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;start_period:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;15s&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f472b6;&quot;&gt;redis:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;image:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;redis:7-alpine&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;# 軽量Linux Alpineベースの公式Redisイメージ（約30MB）&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;container_name:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;my-redis&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;command:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;redis-server --appendonly yes&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;# AOF（Append-Only File）永続化を有効化&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;ports:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;6379:6379&quot;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;# ホストPCのRedisInsightやGUIツールからの接続用&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;volumes:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #fcd34d;&quot;&gt;redisdata:/data&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;# キャッシュデータの永続化領域&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;healthcheck:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;test:&lt;/span&gt; [&lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;CMD&quot;&lt;/span&gt;, &lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;redis-cli&quot;&lt;/span&gt;, &lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;ping&quot;&lt;/span&gt;]&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;interval:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;5s&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;timeout:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;3s&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;retries:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;3&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f472b6;&quot;&gt;webapi:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;build:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;context:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;.&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;dockerfile:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;Dockerfile&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;container_name:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;my-webapi&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;ports:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;5000:8080&quot;&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;environment:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #4ade80;&quot;&gt;ASPNETCORE_ENVIRONMENT=Development&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #4ade80;&quot;&gt;ConnectionStrings__DefaultConnection=Server=db,1433;Database=CatalogDb;User Id=sa;Password=YourStrong@Pass123;TrustServerCertificate=True;&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- &lt;span style=&quot;color: #4ade80;&quot;&gt;ConnectionStrings__Redis=redis:6379&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;# 内部DNS名 &#39;redis&#39; を指定！&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;depends_on:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;db:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;condition:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;service_healthy&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;# SQL Serverの初期化完了を待機&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;redis:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #94a3b8;&quot;&gt;condition:&lt;/span&gt; &lt;span style=&quot;color: #fcd34d;&quot;&gt;service_healthy&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;# Redisのping応答確認を待機&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;

        &lt;span style=&quot;color: #38bdf8;&quot;&gt;volumes:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f472b6;&quot;&gt;sqldata:&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #f472b6;&quot;&gt;redisdata:&lt;/span&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0c4a6e; font-size: 19px; margin-top: 30px; margin-bottom: 12px;&quot;&gt;設定の注目ポイント&lt;/h3&gt;
    &lt;ol style=&quot;line-height: 1.85; margin-bottom: 25px; padding-left: 24px;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;&lt;code&gt;redis:7-alpine&lt;/code&gt; の採用:&lt;/strong&gt; Ubuntuベースのイメージと比べ、わずか約30MBと超軽量でセキュリティフットプリントも最小限です。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;&lt;code&gt;command: redis-server --appendonly yes&lt;/code&gt;:&lt;/strong&gt; デフォルトのスナップショット保存（RDB）に加え、書き込みログを追記保存するAOF（Append-Only File）を有効化し、予期せぬコンテナ停止時もキャッシュデータを保持します。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;内部DNS解決（&lt;code&gt;ConnectionStrings__Redis=redis:6379&lt;/code&gt;）:&lt;/strong&gt; Docker Composeの内部DNSにより、Web APIコンテナからはサービス名の &lt;code&gt;redis&lt;/code&gt; という名前で自動的にIPアドレスが解決されます。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;healthcheck（&lt;code&gt;redis-cli ping&lt;/code&gt;）:&lt;/strong&gt; Redisがリクエストに応答できる（PONGを返す）状態を検知してからWeb APIを起動させます。&lt;/li&gt;
    &lt;/ol&gt;

    &lt;!-- メモリキャッシュ vs 分散キャッシュ --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ C# ASP.NET Core での分散キャッシュ設計（IDistributedCache）&lt;/h2&gt;
    &lt;p&gt;
        C#でキャッシュを扱う際、昔ながらの &lt;code&gt;IMemoryCache&lt;/code&gt; と、モダンな &lt;code&gt;IDistributedCache&lt;/code&gt; には決定的な構造の違いがあります。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/10TPMqhc_J_ID1K3wEH791c2APmeYi2ea&quot; alt=&quot;メモリキャッシュ vs Redis分散キャッシュ&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】単一インメモリキャッシュ（IMemoryCache）の限界 vs Redis分散キャッシュ（IDistributedCache）のスケール耐性&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 25px 0; font-size: 15px;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background: #0284c7; color: white;&quot;&gt;
                &lt;th style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;&quot;&gt;比較項目&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;&quot;&gt;単一インメモリ（IMemoryCache）&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;&quot;&gt;Redis分散キャッシュ（IDistributedCache）&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;保存場所&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1;&quot;&gt;Webアプリコンテナの内部プロセスヒープメモリ&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; color: #0284c7; font-weight: bold;&quot;&gt;独立したRedisコンテナ&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;複数コンテナ（スケール時）&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; color: #dc2626;&quot;&gt;コンテナごとにキャッシュが孤立し不整合発生&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;全コンテナで100%同一キャッシュを共有&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;Webコンテナ再起動時&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; color: #dc2626;&quot;&gt;キャッシュデータがすべて蒸発・消失&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;Redis側にデータが温存され即復旧&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; font-weight: bold;&quot;&gt;標準インターフェース&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;IMemoryCache&lt;/code&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 16px; border: 1px solid #cbd5e1; color: #0284c7; font-weight: bold;&quot;&gt;&lt;code&gt;IDistributedCache&lt;/code&gt;&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;
        ASP.NET Coreは、分散キャッシュのアクセス手段として &lt;code&gt;IDistributedCache&lt;/code&gt; インターフェースを提供しています。&lt;br/&gt;
        このインターフェースを使うことで、アプリケーションコードは「バックエンドがRedisなのか、SQL Serverなのか、テスト用インメモリなのか」を意識することなく、依存性の注入（DI）を通じて透過的にキャッシュを扱えるようになります。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #0c4a6e; font-size: 19px; margin-top: 30px; margin-bottom: 12px;&quot;&gt;NuGetパッケージの導入とDI登録&lt;/h3&gt;
    &lt;p&gt;
        まずは公式のRedisプロバイダーパッケージを追加します。
    &lt;/p&gt;
    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 15px 20px; margin: 15px 0; font-family: Consolas, monospace; font-size: 14.5px;&quot;&gt;
        $ &lt;span style=&quot;color: #38bdf8;&quot;&gt;dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis&lt;/span&gt;
    &lt;/div&gt;
    &lt;p&gt;
        次に &lt;code&gt;Program.cs&lt;/code&gt; で、環境変数から取得した接続文字列を使ってRedisキャッシュサービスを登録します。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 20px 24px; margin: 20px 0; font-family: Consolas, Monaco, monospace; font-size: 14.5px; overflow-x: auto; line-height: 1.75;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;// Program.cs: Redis分散キャッシュの登録&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #c084fc;&quot;&gt;var&lt;/span&gt; redisConnectionString = builder.Configuration.GetConnectionString(&lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;Redis&quot;&lt;/span&gt;) &lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;?? &lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;localhost:6379&quot;&lt;/span&gt;;&lt;br/&gt;&lt;br/&gt;
        builder.Services.AddStackExchangeRedisCache(options =&amp;gt;&lt;br/&gt;
        {&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;options.Configuration = redisConnectionString;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;options.InstanceName = &lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;DockerDemo_&quot;&lt;/span&gt;;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;// キーのプレフィックス（名前空間の衝突防止）&lt;/span&gt;&lt;br/&gt;
        });
    &lt;/div&gt;

    &lt;!-- Cache-Aside パターンの実践フロー --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 実践ハンズオン：Cache-Aside パターン実装と動作検証&lt;/h2&gt;
    &lt;p&gt;
        分散キャッシュ運用のデファクトスタンダードである&lt;strong&gt;「Cache-Aside パターン」&lt;/strong&gt;の処理フローを図解で追ってみましょう。
    &lt;/p&gt;

    
    &lt;div style=&quot;margin: 30px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/17AYJ_cQ7a-7bCrD-sRf5mONyDzRq6UA5&quot; alt=&quot;Cache-Aside パターンの実践フロー&quot; style=&quot;width: 100%; max-width: 820px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.12); display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 13.5px; color: #64748b; margin-top: 8px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】Cache-Aside パターンの3ステップフロー（Redis確認 ➡ DB取得 ➡ TTL付きキャッシュ書き込み）&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #0c4a6e; font-size: 19px; margin-top: 25px; margin-bottom: 12px;&quot;&gt;C# サービス層での Cache-Aside 実装コード&lt;/h3&gt;
    &lt;p&gt;
        商品マスタを取得するサービスクラス &lt;code&gt;CatalogService.cs&lt;/code&gt; を実装します。JSONシリアライズと &lt;code&gt;IDistributedCache&lt;/code&gt; の非同期メソッドを組み合わせます。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 22px 24px; margin: 20px 0; font-family: Consolas, Monaco, monospace; font-size: 14.5px; overflow-x: auto; line-height: 1.75;&quot;&gt;
        &lt;span style=&quot;color: #c084fc;&quot;&gt;using&lt;/span&gt; System.Text.Json;&lt;br/&gt;
        &lt;span style=&quot;color: #c084fc;&quot;&gt;using&lt;/span&gt; Microsoft.Extensions.Caching.Distributed;&lt;br/&gt;
        &lt;span style=&quot;color: #c084fc;&quot;&gt;using&lt;/span&gt; Microsoft.EntityFrameworkCore;&lt;br/&gt;&lt;br/&gt;

        &lt;span style=&quot;color: #c084fc;&quot;&gt;public class&lt;/span&gt; &lt;span style=&quot;color: #38bdf8;&quot;&gt;CatalogService&lt;/span&gt;&lt;br/&gt;
        {&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;private readonly&lt;/span&gt; AppDbContext _dbContext;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;private readonly&lt;/span&gt; IDistributedCache _cache;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;private readonly&lt;/span&gt; ILogger&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;CatalogService&lt;/span&gt;&amp;gt; _logger;&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #38bdf8;&quot;&gt;CatalogService&lt;/span&gt;(AppDbContext dbContext, IDistributedCache cache, ILogger&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;CatalogService&lt;/span&gt;&amp;gt; logger)&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_dbContext = dbContext;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_cache = cache;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_logger = logger;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;public async&lt;/span&gt; Task&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;ProductDto?&lt;/span&gt;&amp;gt; GetProductByIdAsync(&lt;span style=&quot;color: #c084fc;&quot;&gt;int&lt;/span&gt; id)&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;string&lt;/span&gt; cacheKey = &lt;span style=&quot;color: #fcd34d;&quot;&gt;$&quot;product:{id}&quot;&lt;/span&gt;;&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;// ① まずRedisキャッシュを確認&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;string?&lt;/span&gt; cachedJson = &lt;span style=&quot;color: #c084fc;&quot;&gt;await&lt;/span&gt; _cache.GetStringAsync(cacheKey);&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;if&lt;/span&gt; (!&lt;span style=&quot;color: #c084fc;&quot;&gt;string&lt;/span&gt;.IsNullOrEmpty(cachedJson))&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_logger.LogInformation(&lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;⚡ [キャッシュヒット] Redisから即座に返却: Key={Key}&quot;&lt;/span&gt;, cacheKey);&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;return&lt;/span&gt; JsonSerializer.Deserialize&amp;lt;&lt;span style=&quot;color: #38bdf8;&quot;&gt;ProductDto&lt;/span&gt;&amp;gt;(cachedJson);&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;// ② キャッシュミス時：SQL Serverから最新データをクエリ取得&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_logger.LogWarning(&lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;⚠️ [キャッシュミス] SQL Serverへクエリ発行: Id={Id}&quot;&lt;/span&gt;, id);&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;var&lt;/span&gt; product = &lt;span style=&quot;color: #c084fc;&quot;&gt;await&lt;/span&gt; _dbContext.Products.FindAsync(id);&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;if&lt;/span&gt; (product == &lt;span style=&quot;color: #c084fc;&quot;&gt;null&lt;/span&gt;) &lt;span style=&quot;color: #c084fc;&quot;&gt;return null&lt;/span&gt;;&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;var&lt;/span&gt; dto = &lt;span style=&quot;color: #c084fc;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #38bdf8;&quot;&gt;ProductDto&lt;/span&gt;(product.Id, product.Name, product.Price);&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;// ③ 取得したデータをTTL（有効期限）付きでRedisに書き込み&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;var&lt;/span&gt; cacheOptions = &lt;span style=&quot;color: #c084fc;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #38bdf8;&quot;&gt;DistributedCacheEntryOptions&lt;/span&gt;()&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.SetAbsoluteExpiration(TimeSpan.FromMinutes(&lt;span style=&quot;color: #fcd34d;&quot;&gt;10&lt;/span&gt;))&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;// 10分後に自動破棄&lt;/span&gt;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.SetSlidingExpiration(TimeSpan.FromMinutes(&lt;span style=&quot;color: #fcd34d;&quot;&gt;2&lt;/span&gt;));&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #64748b;&quot;&gt;// 2分アクセスが無ければ破棄&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;await&lt;/span&gt; _cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(dto), cacheOptions);&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_logger.LogInformation(&lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;💾 Redisにキャッシュ保存完了: Key={Key}&quot;&lt;/span&gt;, cacheKey);&lt;br/&gt;&lt;br/&gt;

        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #c084fc;&quot;&gt;return&lt;/span&gt; dto;&lt;br/&gt;
        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/&gt;
        }
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #0c4a6e; font-size: 19px; margin-top: 30px; margin-bottom: 12px;&quot;&gt;動作確認：Redis CLI でのキャッシュ検証&lt;/h3&gt;
    &lt;p&gt;
        コンテナを一括起動して、実際にRedisコンテナ内にキャッシュが保存されているか確認してみましょう。
    &lt;/p&gt;

    &lt;div style=&quot;background: #0f172a; color: #f8fafc; border-radius: 8px; padding: 18px 22px; margin: 20px 0; font-family: Consolas, monospace; font-size: 14.5px; line-height: 1.8;&quot;&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 3層コンテナを一括起動&lt;/span&gt;&lt;br/&gt;
        $ &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose up -d --build&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# 初回リクエスト（キャッシュミス ➡ SQL Serverから取得＆Redis保存）&lt;/span&gt;&lt;br/&gt;
        $ &lt;span style=&quot;color: #38bdf8;&quot;&gt;curl http://localhost:5000/api/products/1&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# Redisコンテナ内部に入り、保存されたキーを確認&lt;/span&gt;&lt;br/&gt;
        $ &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose exec redis redis-cli KEYS &quot;*&quot;&lt;/span&gt;&lt;br/&gt;
        1) &lt;span style=&quot;color: #fcd34d;&quot;&gt;&quot;DockerDemo_product:1&quot;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #64748b;&quot;&gt;# キャッシュの残り有効秒数（TTL）を確認&lt;/span&gt;&lt;br/&gt;
        $ &lt;span style=&quot;color: #38bdf8;&quot;&gt;docker compose exec redis redis-cli TTL &quot;DockerDemo_product:1&quot;&lt;/span&gt;&lt;br/&gt;
        (integer) &lt;span style=&quot;color: #4ade80;&quot;&gt;598&lt;/span&gt;
    &lt;/div&gt;

    &lt;p&gt;
        2回目以降のリクエストでは、SQL Serverへのクエリログは一切出力されず、Redisから&lt;strong&gt;わずか1ミリ秒未満で即座にJSONが返却&lt;/strong&gt;されるようになります！
    &lt;/p&gt;

    &lt;!-- YouTube動画連動 --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ YouTube動画連動：霊夢と魔理沙の掛け合い解説&lt;/h2&gt;
    &lt;p&gt;
        本講義の内容は、YouTubeの動画講義（ゆっくり解説）でも楽しくビジュアルに学べます！&lt;br/&gt;
        3層アーキテクチャの劇的な快適さを、霊夢と魔理沙の会話で振り返ってみましょう。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f1f5f9; border-radius: 8px; padding: 20px 24px; margin: 25px 0; border-left: 6px solid #64748b;&quot;&gt;
        &lt;div style=&quot;margin-bottom: 15px;&quot;&gt;
            &lt;strong style=&quot;color: #ef4444;&quot;&gt;霊夢:&lt;/strong&gt;
            「魔理沙！私、オンプレ時代にRedisを導入しようとして、インフラ部門に申請出したら『サーバー調達に1ヶ月かかります』って言われて諦めたトラウマがあるのよね…」
        &lt;/div&gt;
        &lt;div style=&quot;margin-bottom: 15px;&quot;&gt;
            &lt;strong style=&quot;color: #0284c7;&quot;&gt;魔理沙:&lt;/strong&gt;
            「全エンジニアが泣いたオンプレあるあるだな！だがDocker Composeなら、YAMLに &lt;code&gt;redis:7-alpine&lt;/code&gt; と書くだけで5秒後に動き出す！インフラ調達の待ち時間なんて文字通りゼロだぜ！」
        &lt;/div&gt;
        &lt;div style=&quot;margin-bottom: 15px;&quot;&gt;
            &lt;strong style=&quot;color: #ef4444;&quot;&gt;霊夢:&lt;/strong&gt;
            「しかもC#のコードも、&lt;code&gt;IMemoryCache&lt;/code&gt; を &lt;code&gt;IDistributedCache&lt;/code&gt; に差し替えるだけで、Webコンテナを何台に増やしてもデータがピシッと共有されるのが感動的ね！」
        &lt;/div&gt;
        &lt;div&gt;
            &lt;strong style=&quot;color: #0284c7;&quot;&gt;魔理沙:&lt;/strong&gt;
            「そうだ！Cache-AsideパターンでDBの手前にRedisを置くだけで、SQL Serverのクエリ負荷は激減してレスポンスも1ミリ秒台になる！Web API、SQL Server、Redisの3大コンテナ連携こそ、モダンWeb開発の真骨頂だぜ！」
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 落とし穴＆ベストプラクティス --&gt;
    &lt;h2 style=&quot;color: #0369a1; border-bottom: 3px solid #0db7ed; padding-bottom: 10px; margin-top: 50px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑦ 実務でありがちな落とし穴＆ベストプラクティス&lt;/h2&gt;
    &lt;div style=&quot;background: #fff7ed; border: 1px solid #fed7aa; border-left: 5px solid #f97316; border-radius: 8px; padding: 20px 24px; margin: 25px 0;&quot;&gt;
        &lt;h4 style=&quot;color: #9a3412; margin: 0 0 14px 0; font-size: 17px;&quot;&gt;💡 現場で必ず遭遇する Redis 運用の4大落とし穴&lt;/h4&gt;
        
        &lt;p style=&quot;margin: 0 0 14px 0; color: #78350f; font-size: 15.5px; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;落とし穴① キャッシュの有効期限（TTL）を設定せずメモリ枯渇（OOM）を起こす&lt;/strong&gt;&lt;br/&gt;
            Redisはインメモリデータベースのため、物理メモリ上限に達すると新規データの書き込みエラー（&lt;code&gt;OOM command not allowed&lt;/code&gt;）が発生します。&lt;br/&gt;
            キャッシュを登録する際は、必ず &lt;code&gt;DistributedCacheEntryOptions&lt;/code&gt; で &lt;code&gt;AbsoluteExpirationRelativeToNow&lt;/code&gt; を指定し、古いデータが自動的に失効・解放されるように設計してください。
        &lt;/p&gt;

        &lt;p style=&quot;margin: 0 0 14px 0; color: #78350f; font-size: 15.5px; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;落とし穴② キャッシュスタンピード（キャッシュ失効時のDB負荷集中）&lt;/strong&gt;&lt;br/&gt;
            人気商品のデータなど、毎秒数百リクエストが届くキーのTTLが切れた瞬間、全リクエストが同時にSQL Serverへ殺到してDBサーバーが過負荷でダウンすることがあります。&lt;br/&gt;
            これを防ぐため、有効期限に数秒〜数十秒のランダムな「ジッター（揺らぎ）」を加えるか、セマフォによる二重取得防止ロック（SingleFlightパターン）を検討しましょう。
        &lt;/p&gt;

        &lt;p style=&quot;margin: 0 0 14px 0; color: #78350f; font-size: 15.5px; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;落とし穴③ 接続文字列に localhost を指定してしまう罠&lt;/strong&gt;&lt;br/&gt;
            ホストPCでの開発感覚で &lt;code&gt;ConnectionStrings:Redis=localhost:6379&lt;/code&gt; と書いてしまうと、Web APIコンテナ自身の内部を探してしまい &lt;code&gt;SocketFailure&lt;/code&gt; で接続できません。&lt;br/&gt;
            コンテナ間通信では、必ずComposeのサービス名である &lt;code&gt;redis:6379&lt;/code&gt; を指定してください。
        &lt;/p&gt;

        &lt;p style=&quot;margin: 0; color: #78350f; font-size: 15.5px; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;落とし穴④ シリアライズの非同期処理とメモリオーバーヘッド&lt;/strong&gt;&lt;br/&gt;
            &lt;code&gt;IDistributedCache&lt;/code&gt; はバイト配列（&lt;code&gt;byte[]&lt;/code&gt;）または文字列（&lt;code&gt;string&lt;/code&gt;）を扱います。&lt;br/&gt;
            巨大なオブジェクトコレクションを安易にJSONシリアライズしてRedisに格納すると、シリアライズ処理のCPU負荷とメモリ消費が増大します。キャッシュするデータは画面描画に必要な最小限のDTOに絞り込みましょう。
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- 本日のまとめ＆宿題 --&gt;
    &lt;div style=&quot;background: #f0fdf4; border: 1px solid #bbf7d0; border-left: 5px solid #10b981; border-radius: 8px; padding: 20px 24px; margin: 35px 0;&quot;&gt;
        &lt;div style=&quot;font-weight: bold; color: #15803d; font-size: 18px; margin-bottom: 12px;&quot;&gt;📌 本日のまとめ ＆ 明日へのステップ&lt;/div&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; color: #166534; font-size: 15.5px; line-height: 1.8;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;モダン3層アーキテクチャ:&lt;/strong&gt; Web API（ロジック） ＋ Redis（高速キャッシュ） ＋ SQL Server（永続化）の3層により、高スループットとデータの安全性を両立する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;docker-compose.yml へのRedis追加:&lt;/strong&gt; 公式の軽量イメージ（&lt;code&gt;redis:7-alpine&lt;/code&gt;）を指定し、&lt;code&gt;redisdata&lt;/code&gt; ボリュームとAOF永続化で安全なキャッシュ基盤を1コマンドで構築する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;IDistributedCache による疎結合設計:&lt;/strong&gt; C#標準のインターフェースを活用し、Webコンテナの水平スケールアウトや再起動にびくともしない分散キャッシュを実現する。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Cache-Aside パターンの実践:&lt;/strong&gt; 「Redis確認 ➡ DB取得 ➡ TTL付きキャッシュ保存」の3ステップにより、SQL Serverの負荷を最小化し、1ミリ秒台の超高速レスポンスを叩き出す。&lt;/li&gt;
        &lt;/ul&gt;
        &lt;div style=&quot;margin-top: 15px; padding-top: 12px; border-top: 1px dashed #86efac; font-size: 15px; color: #14532d;&quot;&gt;
            &lt;strong&gt;次回【Day 24】予告:&lt;/strong&gt;&lt;br/&gt;
            『docker-compose.yml のGit共有と .env のGit除外ルール』〜機密情報を安全に分離し、チーム開発で安全にリポジトリ共有するベストプラクティス〜
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/2338713073181922454/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-23redis3-web-api-sql-server-redis.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/2338713073181922454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/2338713073181922454'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-23redis3-web-api-sql-server-redis.html' title='【Day 23】Redisキャッシュを追加した3層コンテナアーキテクチャ 〜Web API ＋ SQL Server ＋ Redis の分散キャッシュ・セッション管理をComposeで構築〜'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/1QMMGvPSGKXtVtiEI58_ztEoAKmNYz4xd=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9031334347464664289.post-7819774871393858938</id><published>2026-10-18T18:11:29.664+09:00</published><updated>2026-10-18T18:11:29.664+09:00</updated><title type='text'>【Day 20】プッシュ前の「5大セルフチェックリスト」</title><content type='html'>
&lt;div style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, &#39;Hiragino Kaku Gothic ProN&#39;, Meiryo, sans-serif; line-height: 1.95; color: #1e293b; max-width: 820px; margin: 0 auto; font-size: 16.5px;&quot;&gt;

    &lt;!-- アイキャッチ画像 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/155Nv8ptpJllPFCj3cDShU4Z6PygARgNL&quot; alt=&quot;Git &amp; GitHub 超入門 Day 20&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        
    &lt;/div&gt;
    

    &lt;!-- 専任講師メッセージ --&gt;
    &lt;div style=&quot;display: flex; align-items: flex-start; background: #f0f7ff; border-left: 6px solid #2563eb; border-radius: 8px; padding: 20px 24px; margin: 30px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.04);&quot;&gt;
        &lt;div style=&quot;font-size: 36px; margin-right: 18px; line-height: 1;&quot;&gt;👨‍🏫&lt;/div&gt;
        &lt;div style=&quot;flex: 1; font-size: 16px; color: #1e3a8a; line-height: 1.8;&quot;&gt;
            &lt;strong&gt;皆さん、こんにちは！ 本講座の専任講師です。&lt;/strong&gt;&lt;br/&gt;
            前回のDay 19では、Conventional Commitsと黄金3段構成による世界標準のコミットメッセージ作法を学びましたね。&lt;br/&gt;
            さて、第4部「現場の実践ルール＆規約」の締めくくりとなる本日のテーマは、チーム開発の平和と信頼性を死守する最終防衛ライン、&lt;strong&gt;「プッシュ前の5大セルフチェックリスト」&lt;/strong&gt;です！&lt;br/&gt;
            Subversion (SVN) や Visual SourceSafe (VSS) で長年開発されてきたエンジニアの皆さん、ローカルでコミットが完了した瞬間に「よし終わった！」とばかりに、無意識に &lt;code&gt;git push&lt;/code&gt; を叩いていませんか？&lt;br/&gt;
            ちょっと待ってください！プッシュはあなたの手元の作業領域から、チーム全員とCI/CDサーバーが監視する共有リモート環境へコードを送り出す&lt;strong&gt;「不可逆な境界線」&lt;/strong&gt;です。&lt;br/&gt;
            もしビルドが壊れたコードや、一時確認用の &lt;code&gt;Console.WriteLine&lt;/code&gt;、さらにはデータベース接続文字列やクラウドのAPIキーといった機密情報がリモートにプッシュされてしまったら…チーム全員の作業が停止し、重大なセキュリティインシデントに発展することさえあります。&lt;br/&gt;
            Gitの最大の強みは、&lt;strong&gt;「プッシュする前であれば、ローカルで何回でも手直しできる」&lt;/strong&gt;点にあります。&lt;br/&gt;
            本日は、プロのエンジニアがプッシュ直前の1分間で必ず実行している『5大セルフチェックリスト』と、C#現場での具体的な自動化テクニックを徹底解説します！
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 導入セクション --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;① 導入・本日の達成目標&lt;/h2&gt;
    &lt;p&gt;
        「ローカルリポジトリの中は自分の私有地だが、リモートリポジトリ（GitHub）はチーム全員が走る公道である」——これがGitにおける最も重要なメンタルモデルです。&lt;br/&gt;
        手元のPCでどんなに汚いコードを書き、どんなに散らかったコミットを作ろうと、誰にも迷惑はかかりません。&lt;br/&gt;
        しかし、一度 &lt;code&gt;git push&lt;/code&gt; を実行した瞬間、そのコードはチーム全員のローカルへ同期され、プルリクエストのレビュー対象となり、自動ビルドパイプライン（CI/CD）へと流れていきます。&lt;br/&gt;
        プロのエンジニアは、公道に出る前の「車検」のように、プッシュ直前のセルフチェックを習慣化しています。
    &lt;/p&gt;
    &lt;div style=&quot;background: #f8fafc; border-left: 5px solid #0284c7; padding: 16px 20px; margin: 20px 0; border-radius: 4px;&quot;&gt;
        &lt;strong style=&quot;color: #0369a1; font-size: 17px;&quot;&gt;🎯 本日のゴール&lt;/strong&gt;
        &lt;ul style=&quot;margin: 8px 0 0 0; padding-left: 20px; line-height: 1.85;&quot;&gt;
            &lt;li&gt;コミット（手元保存）とプッシュ（公開同期）の境界線を意識し、事故の根本原因を理解する&lt;/li&gt;
            &lt;li&gt;チームを壊さないための「5大セルフチェックリスト」を完全習得する&lt;/li&gt;
            &lt;li&gt;C#特有の落とし穴（デバッグログ放置、appsettings生パスワード、テスト未実行）を根絶する&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;git rebase -i&lt;/code&gt; と &lt;code&gt;dotnet test&lt;/code&gt; を組み合わせたプロのプッシュ前ルーティンを身につける&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- セクション②: SVN即時コミットの悲劇 vs Gitのローカル防衛 --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;② 【図解】なぜプッシュ前チェックが命運を分けるのか？&lt;/h2&gt;
    &lt;p&gt;
        まずは、集中型バージョン管理（SVN）とGitにおける「変更公開の仕組み」の違いを図解で対比してみましょう。
    &lt;/p&gt;

    &lt;!-- 図解①: SVN悲劇 vs Git防衛 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1sps-rGQn7aLwHAv1Q90uFaBvd45uNnBv&quot; alt=&quot;なぜプッシュ前にチェックが必要なのか？&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解①】SVNの即時コミット悲劇と、Gitの二段階ローカル防衛の対比&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;SVNのトラウマ vs Gitの二段階安心モデル&lt;/h3&gt;
    &lt;ul style=&quot;line-height: 1.95; padding-left: 25px;&quot;&gt;
        &lt;li&gt;&lt;strong&gt;SVNの即時コミット（危険度：高）&lt;/strong&gt;: SVNでは「コミット＝中央サーバー反映」だったため、「あっ、ビルド通らない！」「テストコード消し忘れた！」と気づいたときには既に全社員に破壊されたコードが配られ、オフィスのあちこちから悲鳴が上がっていました。&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Gitの二段階モデル（安心度：極高）&lt;/strong&gt;: Gitでは「コミット（ローカル保存）」と「プッシュ（共有公開）」が明確に分かれています。ローカルでのコミットは単なるセーブポイント。何十回失敗しても、恥ずかしいコミットメッセージを書いても、&lt;strong&gt;プッシュする前に手元で直せば完全な無傷&lt;/strong&gt;です。&lt;/li&gt;
    &lt;/ul&gt;

    &lt;!-- セクション③: 5大セルフチェックリスト --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;③ 【プロの鉄則】プッシュ前の「5大セルフチェックリスト」完全解説&lt;/h2&gt;
    &lt;p&gt;
        プッシュのコマンドを打つ直前、深呼吸して以下の&lt;strong&gt;「5大チェック項目」&lt;/strong&gt;を指差し確認してください。これだけでチームの事故は100%防げます。
    &lt;/p&gt;

    &lt;!-- 図解②: 5大チェック項目 --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1Uy1_cmtc94TIcn8Oicqkno0MsJMmyS97&quot; alt=&quot;プッシュ前 5大セルフチェック項目&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解②】ビルド・デバッグ削除・機密情報・履歴整頓・最新取り込みの5大防衛ライン&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 25px 0; font-size: 15.5px;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background: #1e3a8a; color: white;&quot;&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1; width: 15%;&quot;&gt;チェック項目&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1; width: 35%;&quot;&gt;確認内容とリスク&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1; width: 25%;&quot;&gt;確認用コマンド&lt;/th&gt;
                &lt;th style=&quot;padding: 12px 14px; text-align: left; border: 1px solid #cbd5e1;&quot;&gt;判定基準&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; font-weight: bold; color: #2563eb;&quot;&gt;① ビルド＆テスト&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;ソリューション全体のクリーンビルドと単体テストが通るか？CIを落とす最大の原因。&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;dotnet build -c Release&lt;/code&gt;&lt;br/&gt;&lt;code&gt;dotnet test --no-build&lt;/code&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;0 Errors, ALL PASS&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; font-weight: bold; color: #dc2626;&quot;&gt;② デバッグコード除去&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;一時的なログ出力（Console.WriteLine）やブレークポイント、不要なコメントアウトの放置。&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;git diff origin/main...HEAD&lt;/code&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;一時コード残存ゼロ&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; font-weight: bold; color: #ea580c;&quot;&gt;③ 機密情報混入ゼロ&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;DBパスワード、APIキー、秘密鍵が平文でコミットされていないか？会社の信用失墜リスク。&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;git diff -S&quot;Password&quot;&lt;/code&gt;&lt;br/&gt;&lt;code&gt;git status&lt;/code&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;シークレット完全秘匿&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #f8fafc;&quot;&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; font-weight: bold; color: #7c3aed;&quot;&gt;④ 履歴の整頓&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;「あ」「修正」「動いた」などの小コミットが乱立していないか？レビュー負荷の増大。&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;git log --oneline -n 5&lt;/code&gt;&lt;br/&gt;&lt;code&gt;git rebase -i HEAD~N&lt;/code&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;論理的コミットに集約&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;background: #ffffff;&quot;&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; font-weight: bold; color: #0284c7;&quot;&gt;⑤ 最新親ブランチ取り込み&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;自分が開発中に親ブランチが進んでいないか？PR作成後のコンフリクト発生を防ぐ。&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1;&quot;&gt;&lt;code&gt;git fetch origin&lt;/code&gt;&lt;br/&gt;&lt;code&gt;git merge origin/develop&lt;/code&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 12px 14px; border: 1px solid #cbd5e1; color: #16a34a; font-weight: bold;&quot;&gt;競合ゼロ・最新化完了&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;!-- セクション④: C#現場での必須チェックポイント --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;④ 【図解】C#現場での必須チェックポイント（テスト＆シークレット確認）&lt;/h2&gt;
    &lt;p&gt;
        C#（.NET）開発の現場において、特に頻発するミスとその防止策を図解で整理します。
    &lt;/p&gt;

    &lt;!-- 図解③: C#現場チェック --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1wpzYW666sMzAZXOWFiBWvKM5BtyCv37q&quot; alt=&quot;C#現場での必須チェックポイント&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解③】Console.WriteLine・パスワード混入防止とdotnet testによる全GREEN確認&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;1. 機密情報は &lt;code&gt;UserSecrets&lt;/code&gt; または環境変数へ&lt;/h3&gt;
    &lt;p&gt;
        最も致命的なミスは、&lt;code&gt;appsettings.Development.json&lt;/code&gt; に開発用DBの生パスワードや外部APIトークンを書いたままコミットしてしまうことです。&lt;br/&gt;
        .NETにはローカル開発用の機密情報をリポジトリ外に安全に保存する&lt;strong&gt;「シークレットマネージャー（UserSecrets）」&lt;/strong&gt;が標準搭載されています。
    &lt;/p&gt;
    &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 22px; border-radius: 8px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0; line-height: 1.7;&quot;&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# プロジェクトフォルダでシークレットを初期化&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #60a5fa;&quot;&gt;dotnet user-secrets init&lt;/span&gt;&lt;br/&gt;
        &lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# パスワードやキーを安全に保存（リポジトリの対象外フォルダに保存される）&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #60a5fa;&quot;&gt;dotnet user-secrets set &quot;DbSettings:Password&quot; &quot;SuperSecret123!&quot;&lt;/span&gt;
    &lt;/div&gt;

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;2. 一時デバッグコードの除去と &lt;code&gt;#if DEBUG&lt;/code&gt;&lt;/h3&gt;
    &lt;p&gt;
        &lt;code&gt;Console.WriteLine(&quot;DEBUG: ここを通った&quot;)&lt;/code&gt; や &lt;code&gt;System.Diagnostics.Debugger.Break()&lt;/code&gt; は、動作確認が終わったら必ず消去します。&lt;br/&gt;
        もし開発時のみ実行したい診断処理がある場合は、必ず &lt;code&gt;#if DEBUG&lt;/code&gt; プリプロセッサディレクティブで囲み、Releaseビルドで完全に除外されるように配慮しましょう。
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;3. PowerShellワンライナーによる全自動事前チェック&lt;/h3&gt;
    &lt;p&gt;
        「ビルドとテストを手動で叩くのが面倒」という方は、以下のPowerShellワンライナーを実行するだけで、ビルドからテストまで一括検証できます：
    &lt;/p&gt;
    &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 22px; border-radius: 8px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0; line-height: 1.7;&quot;&gt;
        &lt;span style=&quot;color: #4ade80;&quot;&gt;dotnet test --configuration Release --nologo --verbosity minimal&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 全テストが成功すればグリーンで完了！エラーがあれば即座に赤字で通知&lt;/span&gt;
    &lt;/div&gt;

    &lt;!-- セクション⑤: 履歴の整頓と安全プッシュ --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑤ 【図解】コミット履歴の整頓と安全プッシュフロー&lt;/h2&gt;
    &lt;p&gt;
        プッシュ前の最後の仕上げが&lt;strong&gt;「コミット履歴の整頓（Clean History）」&lt;/strong&gt;です。
    &lt;/p&gt;

    &lt;!-- 図解④: 履歴整頓と安全プッシュ --&gt;
    
    &lt;div style=&quot;margin: 25px 0; text-align: center;&quot;&gt;
        &lt;img src=&quot;https://lh3.googleusercontent.com/d/1hB8Kq9uoPRFF0cMyLMIYFyLptBKUo6NO&quot; alt=&quot;コミット履歴の整頓と安全プッシュ&quot; style=&quot;width: 100%; max-width: 780px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; display: block; margin: 0 auto;&quot; /&gt;
        &lt;div style=&quot;text-align: center; font-size: 14px; color: #64748b; margin-top: 10px; margin-bottom: 25px; font-weight: bold;&quot;&gt;▲ 【図解④】git rebase -i による不要コミット合体とクリーンなプッシュフロー&lt;/div&gt;
    &lt;/div&gt;
    

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;git rebase -i で散らかったコミットを美しくまとめる&lt;/h3&gt;
    &lt;p&gt;
        開発中に細かく「動いた」「typo修正」「あ」と刻んだコミットは、プッシュ前なら &lt;code&gt;git rebase -i&lt;/code&gt; を使って1つの綺麗な &lt;code&gt;feat:&lt;/code&gt; や &lt;code&gt;fix:&lt;/code&gt; コミットに合体（squash）させることができます。
    &lt;/p&gt;
    &lt;div style=&quot;background: #1e293b; color: #f8fafc; padding: 18px 22px; border-radius: 8px; font-family: Consolas, monospace; font-size: 14.5px; margin: 15px 0; line-height: 1.7;&quot;&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# 直近3つのコミットを対話的に整頓&lt;/span&gt;&lt;br/&gt;
        &lt;span style=&quot;color: #60a5fa;&quot;&gt;git rebase -i HEAD~3&lt;/span&gt;&lt;br/&gt;
        &lt;br/&gt;
        &lt;span style=&quot;color: #94a3b8;&quot;&gt;# エディタが開いたら、2行目以降の「pick」を「squash（または s）」に書き換えて保存&lt;/span&gt;&lt;br/&gt;
        pick 1a2b3c4 feat(auth): 認証サービスクラスの追加&lt;br/&gt;
        &lt;span style=&quot;color: #facc15;&quot;&gt;squash&lt;/span&gt; 5d6e7f8 typo修正&lt;br/&gt;
        &lt;span style=&quot;color: #facc15;&quot;&gt;squash&lt;/span&gt; 9g0h1i2 テスト通過用の調整
    &lt;/div&gt;
    &lt;p&gt;
        これだけで、3つの乱雑なコミットが1つの美しい論理コミットへと統合され、プルリクエストのレビュアーも一目で変更内容を把握できるようになります！
    &lt;/p&gt;

    &lt;h3 style=&quot;color: #1e40af; font-size: 19px; margin-top: 25px;&quot;&gt;プッシュ直前の「3大確認コマンド」&lt;/h3&gt;
    &lt;ol style=&quot;line-height: 1.95; padding-left: 25px;&quot;&gt;
        &lt;li&gt;&lt;code&gt;git status&lt;/code&gt;: 意図しない未追跡ファイル（*.tmp や *.log）が残っていないか？&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;git log --oneline -n 3&lt;/code&gt;: 直近のコミットメッセージがConventional Commitsに従っているか？&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;git push -u origin feature/issue-105-user-auth&lt;/code&gt;: 自信を持ってリモートへ送信！&lt;/li&gt;
    &lt;/ol&gt;

    &lt;!-- セクション⑥: 本日のまとめ --&gt;
    &lt;h2 style=&quot;color: #1e3a8a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; margin-top: 45px; margin-bottom: 22px; font-size: 24px;&quot;&gt;⑥ 📌 本日のまとめ・理解したい最重要ポイント&lt;/h2&gt;
    &lt;p&gt;
        第20回の講義、お疲れ様でした！ 第4部「現場の実践ルール＆規約」の総決算として、プッシュ前セルフチェックの最重要ポイントを復習しましょう。
    &lt;/p&gt;

    &lt;div style=&quot;background: #f8fafc; border: 2px solid #3b82f6; border-radius: 8px; padding: 22px 26px; margin: 25px 0;&quot;&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px; line-height: 1.95; color: #1e293b;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;プッシュは「私有地から公道へ出る」不可逆な境界線！&lt;/strong&gt;: ローカルのコミットは何回失敗しても自由だが、プッシュ前の1分間のチェックがチームの平和を守る。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;プッシュ前「5大セルフチェック」を必ず実行！&lt;/strong&gt;: ①ビルド＆テスト（dotnet test）、②一時デバッグコード削除、③機密情報混入ゼロ、④履歴の整頓、⑤最新親ブランチの取り込み。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;C#の機密情報はUserSecretsや環境変数で徹底防衛！&lt;/strong&gt;: &lt;code&gt;appsettings.json&lt;/code&gt; に生の接続文字列やAPIキーを絶対に書かない。&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;散らかったコミットは &lt;code&gt;git rebase -i&lt;/code&gt; で綺麗に整えてからプッシュ！&lt;/strong&gt;: レビュアーへの配慮として、試行錯誤の小コミットは1つの論理的コミットに集約する。&lt;/li&gt;
        &lt;/ul&gt;
        &lt;div style=&quot;margin-top: 18px; padding-top: 15px; border-top: 1px dashed #cbd5e1; font-weight: bold; color: #15803d; font-size: 16px;&quot;&gt;
            次回【Day 21】からは、いよいよ超実践編の第5部「開発フェーズ別・現場ケーススタディ」に突入します！&lt;br/&gt;
            第1弾は&lt;strong&gt;【Case 1】新規開発フェーズ（複数人でのスプリント並行開発）&lt;/strong&gt;をお届けします！複数のC#エンジニアが認証・決済・画面を同時にバリバリ並行開発する現場のリアルな運用フローを体験しましょう。お楽しみに！
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/feeds/7819774871393858938/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-205.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/7819774871393858938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9031334347464664289/posts/default/7819774871393858938'/><link rel='alternate' type='text/html' href='http://www.xn--u9j013gspk3tc5uiht8aow3b.com/2026/10/day-205.html' title='【Day 20】プッシュ前の「5大セルフチェックリスト」'/><author><name>爺</name><uri>http://www.blogger.com/profile/10869434223723994144</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8VIszPjneTtcmXXd4uLmK37_YM3ajI7caz8Xks3_-IXAkCNVq66sGvH99VjIJ066Ov-mLdyqwm4a0XiYkHVqCFsaITS34Ie92Ep4VUo5Zml1tJrGLC1R9NSl-5iR7wZI/s220/F73CDD1A-F20A-4D57-ACBD-D5D7C7CCCED5.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/d/155Nv8ptpJllPFCj3cDShU4Z6PygARgNL=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry></feed>