.NET 8のDocker化: Multi-stage Buildの最適化と本番環境向け構成ガイド

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

なぜ.NET 8にDockerが必要なのか?

「自分のローカル環境では動くのに、サーバーにデプロイするとエラーが出る」というのは、すべての開発者にとっての悩みの種です。その原因の多くは、SDKのバージョン、ランタイム、あるいは環境変数の不一致にあります。.NET 8は優れたパフォーマンスを提供しますが、単にpublishしたファイルをVPSにコピーするだけのデプロイ方法では、プロジェクトの潜在能力を十分に引き出せているとは言えません。

コンテナ化(Dockerize)により、ランタイムとライブラリ全体を単一のImageにパッケージ化できます。しかし、最適化を行わないと、.NETのImageは800MBを超えることもあり、CI/CDの帯域幅を無駄に消費してしまいます。Multi-stage Buildを適用することで、Imageのサイズを約200MBまで軽量化でき、デプロイを瞬時に完了させることが可能になります。

私がDockerを使い始めたばかりの頃、binobjフォルダまで丸ごとImageにコピーしてしまうという初歩的なミスを犯したことがあります。その結果、ビルドは非常に遅く、Imageサイズも膨大になってしまいました。皆さんが同じ過ちを繰り返さないよう、以下に標準的な手順をまとめます。

環境構築の準備

開始する前に、以下のツールがインストールされていることを確認してください:

  • .NET 8 SDK: ローカル開発用の最新バージョン。
  • Docker Desktop: Linuxユーザーの場合はDocker Engine。
  • VS Code / Visual Studio 2022: Docker拡張機能のサポートが充実しています。

練習用にWeb APIプロジェクトを素早く作成します:

dotnet new webapi -n MyDotnetApp
cd MyDotnetApp
dotnet run

Multi-stage BuildによるDockerfileの最適化

この手法では、ビルド環境(重いSDKが必要)と実行環境(最小限のライブラリのみが必要)を分離します。これが、軽量でセキュアなImageを作成するための秘訣です。

1. .dockerignoreファイルの作成

このステップを飛ばさないでください!不要なファイルを除外することで、ビルド時のコンテキスト圧縮時間を短縮できます。

**/.git
**/.vs
**/bin
**/obj
Dockerfile
.dockerignore

2. .NET 8向けの標準的なDockerfile

注意:.NET 8から、Microsoftは従来のポート80のではなく、デフォルトでポート8080を使用するように変更しました。

# ステージ1: ビルドとリストア
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src

# NuGetのレイヤーキャッシュ: .csprojファイルが変更された場合のみリストアを実行
COPY ["MyDotnetApp.csproj", "./"]
RUN dotnet restore "MyDotnetApp.csproj"

# ソースコードのコピーとアプリケーションのビルド
COPY . .
RUN dotnet build "MyDotnetApp.csproj" -c Release -o /app/build

# ステージ2: パブリッシュ
FROM build AS publish
RUN dotnet publish "MyDotnetApp.csproj" -c Release -o /app/publish /p:UseAppHost=false

# ステージ3: 最終イメージ (実行環境のみ)
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
WORKDIR /app
EXPOSE 8080

# アプリの実行に必要なファイルのみをコピー
COPY --from=publish /app/publish .

ENV ASPNETCORE_ENVIRONMENT=Production
ENTRYPOINT ["dotnet", "MyDotnetApp.dll"]

注目すべきポイント: COPY csproj コマンドを COPY . . よりも前に配置しています。これにより、NuGetライブラリの追加がない限り、Dockerはリストア工程のキャッシュを再利用するため、ビルドのたびに1〜2分程度の時間を節約できます。

プロフェッショナルな環境設定管理

実際の開発では、環境(Staging、Production)ごとに異なる appsettings.json ファイルを使用します。Dockerfile内でこれらの値をハードコーディングしてはいけません。

代わりに、環境変数 ASPNETCORE_ENVIRONMENT を活用しましょう。コンテナ実行時にこの値を指定するだけで、Imageを再ビルドすることなく簡単に設定を切り替えることができます。

動作確認と運用

特定のタグを指定してImageをビルドします:

docker build -t my-dotnet-app:v1 .

コンテナを起動し、ホストマシンのポート5000をコンテナのポート8080にマッピングします:

docker run -d -p 5000:8080 --name my-app -e ASPNETCORE_ENVIRONMENT=Staging my-dotnet-app:v1

http://localhost:5000/swagger にアクセスして確認してください。デバッグのためにログを確認したい場合は、次のコマンドを使用します: docker logs -f my-app

本番環境向けのTips

.NET 8では常に Health Checks を設定するようにしましょう。DockerやKubernetesは、このエンドポイントを監視し、アプリケーションがデッドロックに陥ったりデータベース接続を失ったりした場合に、自動的にコンテナを再起動します。これにより、深夜に手動で対応することなく、システムが自己修復できるようになります。

Dockerfileと環境管理をマスターすることは、デプロイ作業を楽にするだけでなく、プロフェッショナルなバックエンドエンジニアとしてのシステム思考を証明することにも繋がります。

Share: