Conteneurisation d'applications C# dans Docker : niveau avancé

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : pourquoi le niveau avancé ?

\n

La conteneurisation d'applications C# basées sur .NET n'est plus simplement une tendance — c'est un standard industriel. Au niveau débutant, un Dockerfile basique avec FROM mcr.microsoft.com/dotnet/aspnet suffit. Cependant, dans un environnement de production, des défis apparaissent qui nécessitent une compréhension plus approfondie : minimisation de la taille de l'image, sécurité, architecture multi-conteneurs, gestion efficace de la configuration et débogage.

\n

Cet article est destiné aux développeurs qui connaissent déjà les bases de Docker et C#, mais souhaitent passer au niveau supérieur. Nous aborderons des techniques avancées qui vous permettront de créer des images légères, sécurisées et facilement évolutives pour vos applications .NET.

\n\n

1. Construction multi-étapes (Multi-stage build) : l'art des images légères

\n

Le problème classique — les images .NET SDK pèsent plus de 1,5 Go. Les emporter en production est inutile et dangereux. La construction multi-étapes résout ce problème en séparant l'étape de compilation et l'étape d'exécution.

\n\n

Dockerfile avancé avec multi-stage

\n

Au lieu de simplement copier les fichiers binaires, nous utilisons les images SDK officielles pour la compilation, puis nous copions le résultat dans une image minimale aspnet.

\n
# Étape 1 : Compilation\nFROM mcr.microsoft.com/dotnet/sdk:8.0 AS build\nWORKDIR /app\n\n# Copier uniquement les fichiers du projet (optimisation du cache)\nCOPY src/MyApp.csproj .\nRUN dotnet restore\n\n# Copier le reste du code\nCOPY src/ .\nRUN dotnet publish -c Release -o /app/publish\n\n# Étape 2 : Runtime\nFROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime\nWORKDIR /app\n\n# Ajouter un utilisateur non privilégié\nRUN adduser --disabled-password --gecos '' appuser\nUSER appuser\n\nCOPY --from=build /app/publish .\n\nEXPOSE 8080\nENV ASPNETCORE_URLS=http://+:8080\nENTRYPOINT ["dotnet", "MyApp.dll"]
\n

Ce qui est important ici :

\n
    \n
  • Mise en cache des couches : d'abord, seul le fichier .csproj est copié et dotnet restore est exécuté. Tant que les dépendances ne changent pas, Docker utilisera le cache pour cette couche.
  • \n
  • Utilisateur non privilégié : appuser — crucial pour la sécurité en production.
  • \n
  • Port 8080 : dans .NET 8, le port 8080 est utilisé par défaut, ce qui correspond aux normes cloud modernes.
  • \n
\n\n

Astuce : Compilation Trimmed et AOT

\n

Pour réduire encore plus la taille, utilisez Trimming (suppression du code inutilisé) ou Native AOT. Cela permet d'obtenir des images de 10 à 30 Mo.

\n
# Pour ReadyToRun (R2R) et Trimming\nRUN dotnet publish -c Release -r linux-x64 --self-contained true \\\n    -p:PublishTrimmed=true \\\n    -p:PublishSingleFile=true \\\n    -o /app/publish
\n

Important : AOT impose des limitations sur la réflexion et le chargement dynamique d'assemblages. Avant de l'utiliser, assurez-vous que votre code est compatible.

\n\n

2. Gestion de la configuration et des secrets

\n

Stocker les chaînes de connexion et les clés API à l'intérieur de l'image est une erreur grossière. Au niveau avancé, nous utilisons Docker Secrets, les variables d'environnement et la liaison avec appsettings.json.

\n\n

Surcharge de appsettings via Docker

\n

Dans .NET, il existe un mécanisme intégré de priorités de configuration. Nous pouvons transmettre les paramètres via des variables d'environnement, qui sont automatiquement mappées aux sections de configuration.

\n
// Dans le code C#\nvar builder = WebApplication.CreateBuilder(args);\nbuilder.Configuration\n    .AddJsonFile("appsettings.json", optional: false)\n    .AddEnvironmentVariables(); // Surcharge les valeurs du JSON
\n

Lancement du conteneur :

\n
docker run -d -p 8080:8080 \\\n  -e "ConnectionStrings__DefaultConnection=Server=db;Database=myapp;User Id=sa;Password=MyPass123!" \\\n  -e "Logging__LogLevel__Default=Warning" \\\n                

Blogs

Book Recommendations