docker について
コンテナのビルド、実行環境、ヘルスモニタリングを扱う、.NET 開発者向けの Docker 実践ガイドです。マルチステージビルド、非 root 実行、オーケストレーター側のプローブを重視します。
主な機能
- 01マルチステージイメージビルド
- 02非 root 実行
- 03NuGet レイヤーキャッシュ
- 04オーケストレーターのヘルスプローブ
- 05Docker Compose によるローカル開発
- 06イメージとシークレットの扱い
活用シーン
- 01ASP.NET Web API コンテナの構築
- 02ローカルサービス依存関係の設定
- 03コンテナのヘルスモニタリング設定
- 04CI ビルドとイメージサイズの最適化
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ codewithmukesh/ dotnet-claude-kit --skill dockerインストール後、Claude Code で/dockerを入力して読み込まれたか確認します。
詳細
Docker
基本原則
- 常にマルチステージビルドを使用する — ビルドステージとランタイムステージを分離します。SDK イメージでビルドし、ASP.NET ランタイムイメージで実行します。
- デフォルトで非 root ユーザーを使用する — .NET コンテナーイメージでは、.NET 8 以降、デフォルトで
USER appがサポートされています。本番環境では root として実行しないでください。 - レイヤーキャッシュは重要です — ソースコードをコピーする前に
.csprojファイルをコピーして復元します。これにより、ビルド間で NuGet の依存関係がキャッシュされます。 - ヘルスプローブはオーケストレーター側で実行する —
/health/liveエンドポイントを公開し、Kubernetes/Compose からプローブします。Chiseled イメージとデフォルトの aspnet イメージにはシェルも curl もないため、イメージ内で実行するHEALTHCHECKコマンドには実行手段がありません。
パターン
Web API 用のマルチステージ Dockerfile
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
# Copy project files and restore (cached layer)
COPY ["src/MyApp.Api/MyApp.Api.csproj", "src/MyApp.Api/"]
COPY ["src/MyApp.Domain/MyApp.Domain.csproj", "src/MyApp.Domain/"]
COPY ["Directory.Build.props", "."]
COPY ["Directory.Packages.props", "."]
RUN dotnet restore "src/MyApp.Api/MyApp.Api.csproj"
# Copy everything and build
COPY . .
RUN dotnet publish "src/MyApp.Api/MyApp.Api.csproj" \
-c Release \
-o /app/publish \
--no-restore
# Stage 2: Runtime
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
WORKDIR /app
# Non-root user (default in .NET 8+ images)
USER app
COPY --from=build /app/publish .
EXPOSE 8080
ENTRYPOINT ["dotnet", "MyApp.Api.dll"]
コンテナーのヘルスプローブ
Dockerfile の HEALTHCHECK よりも、オーケストレーター側のプローブ(Kubernetes の livenessProbe、Compose の
healthcheck)を優先してください。標準の aspnet イメージと
Chiseled イメージにはシェルも curl も wget も含まれていないため、コンテナー内でプローブを実行する手段がありません。オーケストレーターの接続先を /health/live に設定してください。
# docker-compose — probe from outside the app process
services:
api:
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health/live || exit 1"]
interval: 30s
timeout: 3s
retries: 3
# Note: CMD-SHELL requires a shell + wget in the image. Use a non-chiseled
# variant for this, or better: let Kubernetes httpGet probes do it —
# they run from the kubelet, needing nothing inside the image.
イメージ内で HEALTHCHECK を実行する必要がある場合は、wget を含む
Chiseled ではないイメージをランタイムステージのベースにしてください。プローブコマンドでアプリのバイナリを再実行してはいけません。最初のインスタンスを確認する代わりに、2 つ目のインスタンスを起動してしまいます。
.dockerignore
**/.git
**/.vs
**/bin
**/obj
**/node_modules
**/Dockerfile*
**/docker-compose*
**/tests
ローカル開発用の Docker Compose
.NET 固有の重要な注意点として、接続文字列は環境変数で渡し、ヘルスチェック付きの depends_on を使用します。
services:
api:
build:
context: .
dockerfile: src/MyApp.Api/Dockerfile
ports:
- "5000:8080"
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__Default=Host=postgres;Database=myapp;Username=postgres;Password=postgres
- ConnectionStrings__Redis=redis:6379
depends_on:
postgres:
condition: service_healthy
# Add postgres/redis services with healthcheck — standard boilerplate
.slnx を使用した最適化ビルド
複数のプロジェクトがあるソリューションでは、必要なプロジェクトのみを復元します。
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
# Copy solution and all project files
COPY *.slnx .
COPY Directory.Build.props .
COPY Directory.Packages.props .
COPY src/**/*.csproj ./src/
# Restore project structure
RUN for file in src/**/*.csproj; do \
mkdir -p $(dirname $file) && mv $file $(dirname $file)/; \
done
RUN dotnet restore
COPY . .
RUN dotnet publish src/MyApp.Api -c Release -o /app/publish --no-restore
ヘルスチェックエンドポイント
// In Program.cs — lightweight health endpoint for Docker
app.MapGet("/health/live", () => Results.Ok("healthy"))
.ExcludeFromDescription();
アンチパターン
ランタイムに SDK イメージを使用しない
# BAD — SDK image is 900MB+, includes compilers
FROM mcr.microsoft.com/dotnet/sdk:10.0
COPY . .
RUN dotnet run
# GOOD — separate build and runtime, runtime image is ~200MB
FROM mcr.microsoft.com/dotnet/aspnet:10.0
復元前にすべてをコピーしない
# BAD — any source change invalidates the NuGet cache
COPY . .
RUN dotnet restore
# GOOD — copy only project files first, then restore
COPY ["src/MyApp.Api/MyApp.Api.csproj", "src/MyApp.Api/"]
RUN dotnet restore "src/MyApp.Api/MyApp.Api.csproj"
COPY . .
root として実行しない
# BAD — running as root (security risk)
FROM mcr.microsoft.com/dotnet/aspnet:10.0
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyApp.Api.dll"]
# GOOD — use the built-in non-root user
FROM mcr.microsoft.com/dotnet/aspnet:10.0
USER app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyApp.Api.dll"]
選択ガイド
| シナリオ | 推奨事項 |
|---|---|
| Web API コンテナー | aspnet ランタイムイメージを使用したマルチステージビルド |
| Worker サービス | dotnet/runtime イメージを使用したマルチステージビルド |
| ローカル開発 | サービスの依存関係を設定した Docker Compose |
| CI ビルド | マルチステージビルド(自己完結型) |
| イメージサイズの最適化 | 小さいイメージには Alpine バリアントとトリミングを使用 |
| ヘルスモニタリング | /health エンドポイントとオーケストレータープローブ(K8s httpGet/Compose healthcheck) |
| シークレット | 環境変数またはマウントされたシークレットを使用し、イメージには含めない |
コメント
Markdown 対応