Skip to content

MS_DotNetCoreDockerization

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

.NET CoreのDockerコンテナ化

  • 戻る(.NET Core
    • .NET CoreのDockerfile(MS_DotNetCoreDockerfile.md
    • .NET CoreのDockerコンテナ化

概要

.NET Core の Docker コンテナ化に必要な検討事項。

補足(このページの位置づけ): 「Dockerfile をどう書くか」ではなく、
**「コンテナに載せるためにアプリ側を何を直すか」**を扱うページである。
コンテナ化の作業は、実際には

① アプリの前提を変える(本ページ)
     ・設定の外出し、パス、URL、セッション、証明書
② Dockerfile を書く(.NET CoreのDockerfile)
③ Compose / K8s で束ねる(コンテナのチェーン)

という 3 層に分かれ、① を飛ばすと動かない

詳細

プログラム

初期化処理

Program.cs、Startup.cs などの初期化処理を変更する。

補足(なぜセッションと「データ保護」が要点なのか): コンテナは
使い捨てで、複数インスタンスに増えることが前提になる。
このため、プロセス内に状態を持つ実装が破綻する

項目 何が起きるか 対処
セッション インスタンスごとに別のセッション Redis 等の分散キャッシュへ外出し
データ保護キー Cookie の暗号化鍵がインスタンスごとに違う → 認証が壊れる 鍵を共有ストレージに永続化
ローカル ファイル 再起動で消える ボリューム or オブジェクト ストレージ

特に データ保護(Data Protection) の見落としは典型的な事故で、
「ログインできるが、リロードすると落ちる」
「インスタンスを増やした途端に認証が不安定になる」という形で現れる。
ASP.NET Core は認証 Cookie や CSRF トークンをこの鍵で保護しているため、
鍵の共有はコンテナ化の必須作業である。

ファイル

  • 使用するファイルは以下の 2 つの方法で、コンテナに含める。
  • 何れの方法も、プロジェクト・ファイルの変更が必要になる。

プロジェクト出力に含める。

プロジェクト出力に含めると、
Dockerfile の以下コマンドでコンテナに出力される。

RUN dotnet publish -c release -o /app
...
COPY --from=build /app ./

埋め込まれたリソースに変更する。

埋め込まれたリソースとして埋め込む。

Dockerfile(MS_DotNetCoreDockerfile.md

開発用から本番用に切り替える。

コチラ(.NET CoreのDockerfile(MS_DotNetCoreDockerfile.md))でも言及した通り、別物なので。

補足(開発用と本番用が別物である理由): Visual Studio が生成する
Dockerfile はデバッガをアタッチするための構成を含んでおり、
そのまま本番に使うものではない。

【本番用】マルチステージ ビルド
  FROM sdk        AS build    … ビルドだけに使う(重い)
  FROM aspnet     AS final    … 実行時はランタイムのみ(軽い)

**SDK イメージ(約 700MB〜)と ASP.NET ランタイム イメージ(約 200MB)**では
サイズが大きく違うため、マルチステージにするだけで効果がある。
さらに小さくしたい場合は、Alpine 版
chiseled(distroless 相当)イメージを選ぶ。

必要なファイルを指定のパスにコピーする。

COPY ["MultiPurposeAuthSiteCore/aspnetapp.pfx", "./"] # Added

補足(証明書をイメージに焼き込まないこと): 上記は検証用の手法である。
.pfx をイメージに含めると、イメージを取得できる者が
秘密鍵を取り出せる
。本番では、

  • ボリューム / Secret でマウントする(K8s の Secret、Docker Secret)、
  • Key Vault から起動時に取得する、
  • そもそもTLS 終端を手前に置くApplication Gateway
    Ingress、リバース プロキシ)、

のいずれかにする。3 つ目が最も素直で、
AppService閉域構成テクニカルリファレンス
AKS の構成でも標準的な形になる。

通信

外部通信・内部通信

外部通信か、内部通信かを検討する。

  • 外部通信

    • Docker Compose の ports でコンテナ・ポートをホスト・ポートにマッピングする。
    • Cookie を伴う外部通信は HTTPS 化が必要になる事が多い。
  • 内部通信

    • Docker Compose の networks で同一のネットワークに含めて通信可能にする。
    • 内部通信は HTTP のままにする必要がある。

HTTPS 化

//app.UseHttpsRedirection();

補足(外は HTTPS・中は HTTP という構成): これは
TLS 終端を境界に置くという一般的な構成である。

ブラウザ ──HTTPS──▶ [ 境界(ports 公開 / Ingress )] ──HTTP──▶ コンテナ間
                       ↑ ここで TLS を終端            ↑ 同一ネットワーク内

内部を HTTP にする理由は、原文が挙げる
**「自己署名証明書の検証ができない」**が実務上は最大である
(コンテナごとに正規の証明書を用意するのは非現実的)。

ただし、ゼロトラストの観点では内部も暗号化すべきという要求もあり、
その場合はサービス メッシュ(Istio 等)の
mTLS で、アプリを変えずに暗号化する方法が採られる。

UseHttpsRedirection() を無効化する点も重要で、
これを残すと内部通信が HTTPS へリダイレクトされて無限ループする

設定

URL から仮想ディレクトリを削除する。

コンテナの場合はルートディレクトリは仮想ディレクトリでない。

補足: IIS では https://host/AppName/ のように
仮想ディレクトリ配下に配置するのが普通だが、
コンテナでは 1 コンテナ 1 アプリなのでルートに置く
パスをハードコードしていると壊れるため、
Url.Content("~/...")<base href> を使うよう直す必要がある。

パスを Linux 仕様に変更する。

  • Windows パスだと Linux 上で認識しない。
  • 標準で Linux パスにしてしまっても良い。
    Linux パスは Windows 上で認識するため。

補足: 原文の「Linux パスは Windows 上で認識する」は、
Windows API が /\ と同様に扱うためである。
ただし最も安全なのは Path.Combine / Path.DirectorySeparatorChar を使い、
パスを文字列連結で組み立てないこと。
併せて、ファイル名の大文字小文字も Linux では区別される点に注意
.NET Coreの開発 参照)。

環境変数で設定を上書き可能にする。

  • 環境変数は、Docker Compose で設定すると楽。
  • 内部通信のホスト名は、サービス名に変更する。
  • 以下の例では ConnectionString_XXX 変数を上書きしている。
environment:
  - UseUrl=http://0.0.0.0:5000/;https://0.0.0.0:5001/
  - RedisConfig=redis
  - RedisInstanceName=redis
  - ASPNETCORE_Kestrel__Certificates__Default__Password=seigi@123
  - ASPNETCORE_Kestrel__Certificates__Default__Path=/app/aspnetapp.pfx
  - ConnectionString_SQL=Data Source=sqlserver;Initial Catalog=Northwind;User ID=sa;Password=seigi@123;
  - ConnectionString_MCN=Server=mysql;Database=test;User Id=root;Password=seigi@123;
  - ConnectionString_NPS=HOST=postgres;DATABASE=postgres;USER ID=postgres;PASSWORD=seigi@123;

補足(この設定の読み方): 2 つの重要な仕組みが使われている。

① 二重アンダースコアによる階層指定

ASPNETCORE_Kestrel__Certificates__Default__Path は、
appsettings.json の次の階層に対応する。

{ "Kestrel": { "Certificates": { "Default": { "Path": "..." } } } }

.NET Core config構成プロバイダーの仕組みで、
環境変数が JSON の設定を上書きする(後勝ち)。
: は Linux の環境変数名に使えないため __ を使う。

② サービス名による名前解決

Server=sqlserver RedisConfig=redis のように、
Compose のサービス名がそのままホスト名になる
(Docker の内蔵 DNS が解決する)。
IP を書かずに済むため、コンテナの再作成に強い。

注意: この例は検証用なのでパスワードが平文である。
本番では Docker Secret / K8s Secret、
あるいは Key Vaultマネージド ID を使い、
接続文字列に秘密を書かない構成にすること。

参考

github.com

以下を比較すると良い。

OSS コンソーシアム

Open 棟梁 Wiki

Docker対応(OTR_DockerSupport.md

開発基盤部会 Wiki

  • ASP.NET Coreをコンテナ化する際の設定ポリシー(DNET_ASPNETCoreContainerPolicy.md
  • ASP.NET Coreをスクラッチでコンテナ化する際の手順(DNET_ASPNETCoreContainerSteps.md

Tags: 移行, .NET開発, .NET Core, 仮想化

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally