关于 docker
面向 .NET 开发者的 Docker 容器化实践指南,涵盖构建、运行和健康监测。重点包括多阶段构建、非 root 运行和编排器级探针。
主要功能
- 01多阶段镜像构建
- 02非 root 用户运行
- 03NuGet 层缓存
- 04编排器健康探针
- 05Docker Compose 本地开发
- 06镜像与密钥处理建议
适用场景
- 01构建 ASP.NET Web API 容器
- 02配置本地服务依赖
- 03设置容器健康监测
- 04优化 CI 构建和镜像体积
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ codewithmukesh/ dotnet-claude-kit --skill docker安装后在 Claude Code 中输入/docker确认已加载。
详细介绍
Docker
核心原则
- 始终使用多阶段构建 — 分离构建阶段和运行时阶段。在 SDK 镜像中构建,在 ASP.NET 运行时镜像中运行。
- 默认以非 root 用户运行 — 自 .NET 8 起,.NET 容器镜像默认支持
USER app。生产环境中绝不要以 root 用户运行。 - 分层缓存很重要 — 先复制
.csproj文件并还原依赖项,再复制源代码。这样可以在不同构建之间缓存 NuGet 依赖项。 - 在编排器层级配置健康探测 — 暴露
/health/live端点,并让 Kubernetes/Compose 对其进行探测。Chiseled 镜像和默认的 aspnet 镜像没有 shell 或 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"]
容器健康探测
优先使用编排器层级的探测(Kubernetes 的 livenessProbe、Compose 的
healthcheck),而不是 Dockerfile HEALTHCHECK — 标准的 aspnet 和
Chiseled 镜像不包含 shell、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 镜像构建运行时阶段 — 绝不要在探测命令中重新运行应用二进制文件;这会启动第二个实例,而不是检查第一个实例。
.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