Docker 和 C#:高级应用程序容器化
使用 Docker 对 .NET 应用程序进行容器化已成为行业标准。如果您已经掌握了基本的容器操作技能,那么是时候进入高级阶段了。在本文中,我们将探讨复杂场景:多阶段构建 (multi-stage build)、创建轻量级生产镜像、使用 Docker Compose 组织微服务、引入健康检查 (health checks) 以及高效管理配置。所有示例均适用于 .NET 8 和最新版本的 Docker。
1. .NET 的多阶段构建 (Multi-stage build)
一个经典问题是镜像体积巨大,包含了 SDK 和构建工具。解决方案是多阶段构建,其中最终镜像仅包含运行时和编译后的二进制文件。
让我们看一个用于 ASP.NET Core Web API 的高级 Dockerfile:
# 阶段 1:还原依赖项FROM mcr.microsoft.com/dotnet/sdk:8.0 AS restoreWORKDIR /srcCOPY ["MyApp.Api/MyApp.Api.csproj", "MyApp.Api/"]COPY ["MyApp.Core/MyApp.Core.csproj", "MyApp.Core/"]RUN dotnet restore "MyApp.Api/MyApp.Api.csproj"
# 阶段 2:构建和发布FROM restore AS buildCOPY . .WORKDIR "/src/MyApp.Api"RUN dotnet publish -c Release -o /app/publish
# 阶段 3:最终镜像 (仅运行时)FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS finalWORKDIR /appEXPOSE 8080ENV ASPNETCORE_URLS=http://+:8080COPY --from=build /app/publish .ENTRYPOINT ["dotnet", "MyApp.Api.dll"]关键优化点:
- 分离 restore 和 build: 缓存包含依赖项的层可以加速后续构建。
- 目标平台: 如果已执行 restore,则在 publish 阶段使用
--no-restore。 - 最小化层数: 尽可能通过
&&合并RUN命令。 - 使用
--chmod: 确保 Linux 容器中的权限正确。
2. 用于 C# 微服务的 Docker Compose
在处理多个 .NET 服务时,Docker Compose 不可或缺。高级场景包括配置网络、依赖项和环境变量。
这是一个用于包含 API Gateway、订单服务和 RabbitMQ 的微服务架构的 docker-compose.yml 示例:
version: '3.8'
services: rabbitmq: image: rabbitmq:3-management-alpine ports: - "5672:5672" - "15672:15672" healthcheck: test: ["CMD", "rabbitmq-diagnostics", "check_port_connectivity"] interval: 30s timeout: 10s retries: 5
orders-api: build: context: . dockerfile: src/Orders.Api/Dockerfile ports: - "5001:8080" environment: - ASPNETCORE_ENVIRONMENT=Production - ConnectionStrings__DefaultConnection=Server=db;Database=OrdersDb;User=sa;Password=Your_password123; - RabbitMQ__Host=rabbitmq depends_on: rabbitmq: condition: service_healthy db: condition: service_started restart: unless-stopped
api-gateway: build: context: . dockerfile: src/ApiGateway/Dockerfile ports: - "80:8080" depends_on: - orders-api environment: - ASPNETCORE_ENVIRONMENT=Production - Services__Orders=http://orders-api:8080高级技巧:
- Compose 中的健康检查: 使用
condition: service_healthy实现严格的依赖关系。 - 配置文件 (profiles): 为不同的开发环境启用/禁用服务。
- 用于日志的内置卷: 使用
volumes:将日志保存在容器外部。
```