Docker et C# : conteneurisation d'applications au niveau avancé
La conteneurisation d'applications .NET avec Docker est devenue un standard de l'industrie. Si les compétences de base avec les conteneurs sont déjà maîtrisées, il est temps de passer au niveau avancé. Dans cet article, nous aborderons des scénarios complexes : la construction multi-étapes (multi-stage build), la création d'images de production légères, l'organisation de microservices avec Docker Compose, l'intégration de health checks et la gestion efficace de la configuration. Tous les exemples sont valables pour .NET 8 et les dernières versions de Docker.
1. Construction multi-étapes (Multi-stage build) pour .NET
Le problème classique est celui des images volumineuses incluant le SDK et les outils de construction. La solution est la construction multi-étapes, où l'image finale ne contient que le runtime et les fichiers binaires compilés.
Examinons un Dockerfile avancé pour ASP.NET Core Web API :
# Étape 1 : Restauration des dépendancesFROM 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"
# Étape 2 : Construction et publicationFROM restore AS buildCOPY . .WORKDIR "/src/MyApp.Api"RUN dotnet publish -c Release -o /app/publish
# Étape 3 : Image finale (runtime uniquement)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"]Optimisations clés :
- Séparation de restore et build : la mise en cache de la couche des dépendances accélère les constructions répétées.
- Plateforme cible : utilisez
--no-restoreà l'étape publish si restore a déjà été effectué. - Minimisation des couches : combinez les commandes
RUNlorsque c'est possible avec&&. - Utilisation de
--chmod: pour des droits d'accès corrects dans les conteneurs Linux.
2. Docker Compose pour les microservices en C#
Docker Compose est indispensable pour travailler avec plusieurs services .NET. Un scénario avancé inclut la configuration du réseau, des dépendances et des variables d'environnement.
Exemple de docker-compose.yml pour une architecture microservices avec API Gateway, service de commandes et RabbitMQ :
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:8080Techniques avancées :
- Healthcheck dans Compose : utilisez
condition: service_healthypour des dépendances strictes. - Profils (profiles) : activez/désactivez des services pour différents environnements de développement.
- Volumes intégrés pour les logs :
volumes:pour conserver les logs en dehors du conteneur. - Variables d'environnement via fichier .env : stockez les données sensibles