Skip to main content

Bonnes pratiques pour la conteneurisation des applications .NET

Écrit par

Marcelo Oliveira

hero container aps

31 août 2022

0 minutes de lecture

La conteneurisation avec Docker est devenue une tendance majeure dans le développement d’applications web, adoptée par de nombreux développeurs .NET. La conteneurisation des applications .NET présente de nombreux avantages pour les développeurs et les ingénieurs DevOps, même lorsqu’ils travaillent avec les anciennes versions 4.x de .NET Framework. Toutefois, si nous ne savons pas utiliser correctement les conteneurs, nous en tirerons peu d’avantages.

Dans cet article, nous allons présenter quelques bonnes pratiques pour conteneuriser les applications .NET, y compris celles utilisant le framework version 4.x. Nous parlerons également de l’utilisation d’images légères et de l’analyse des images afin de réduire les risques de sécurité et de supprimer les composants inutiles de nos conteneurs.

Prérequis

Avant de commencer, vous aurez besoin de :

Pensez à conteneuriser vos applications .NET (même .NET Framework 4.x)

Depuis .NET Core 1.0, les applications web sont multiplateformes, portables et open source. Les développeurs peuvent ainsi les porter vers Docker et tirer pleinement parti de la conteneurisation.

Cependant, si les nouvelles versions de .NET exécutées sous Linux retiennent toute l’attention, les conteneurs Windows prennent en charge les anciennes versions de .NET réservées à Windows, dont dépendent d’innombrables applications d’entreprise. Et toutes les organisations qui assurent la maintenance d’applications web .NET Framework ne sont pas prêtes à les porter vers des versions plus récentes. C’est pourquoi il est judicieux de conteneuriser nos applications .NET Framework 4.x.

Les étapes suivantes montrent comment créer et exécuter une application ASP.NET Web Forms conteneurisée dans Visual Studio 2022.

Commencez par lancer Docker Desktop sur votre machine de développement :

Résultats de recherche Windows pour « docker desktop », avec Docker Desktop affiché comme meilleure correspondance.

Dans la fenêtre Get started de Visual Studio, sélectionnez Create a new project.

Écran de démarrage de Visual Studio, avec l’option « Créer un nouveau projet » encadrée en rouge.

Saisissez « Web Forms » dans la zone de texte Search for templates, puis sélectionnez ASP.NET Web Application (.NET Framework).

Résultats de recherche Visual Studio pour « Web Forms », présentant le modèle de projet d’application Web ASP.NET avec les étiquettes C#, Windows, Cloud et Web

Saisissez le nom de votre nouvelle application (par exemple, WebFormsApp), indiquez son emplacement sur le disque, sélectionnez .NET Framework 4.8, puis cliquez sur Create.

Boîte de dialogue de Visual Studio pour configurer un nouveau projet d’application web ASP.NET nommé WebFormsApp avec .NET Framework 4.8

Sélectionnez ensuite le type Web Forms.

Écran de création d’une application Web ASP.NET affichant les modèles de projet « Vide » et « Web Forms », accompagnés de leurs descriptions

Vérifiez que les options Web Forms et Docker support sont cochées, puis cliquez sur Create.

Boîte de dialogue de création de projet présentant les options de dossier et de référence principale, les paramètres avancés, un champ de projet de test désactivé, ainsi que les boutons Retour et Créer.

Attendez que Visual Studio crée le projet. Voici la structure du projet telle qu’elle apparaît dans Visual Studio :

Explorateur de solutions Visual Studio affichant la structure du projet WebFormsApp avec ses fichiers et dossiers ASP.NET, ainsi que ses fichiers de configuration.

Ouvrez maintenant Docker Desktop. Vous remarquerez que le conteneur WebFormsApp s’exécute sur le port 61469 :

Vue des conteneurs dans Docker Desktop, affichant le conteneur WebFormsApp en cours d’exécution sur le port 61469

Ouvrez l’onglet Images pour voir l’image WebFormsApp, à partir de laquelle le conteneur WebFormsApp s’exécute.

Écran Images sur disque de Docker Desktop affichant deux images locales totalisant 8,64 Go, dont webformsapp avec le tag dev.

Enfin, appuyez sur Ctrl+F5 pour créer votre image Docker et l’exécuter localement. Une fois l’image du conteneur créée et en cours d’exécution dans un conteneur Docker, Visual Studio ouvre l’application web dans votre navigateur par défaut.

Fenêtre de navigateur affichant la page d’accueil d’une application ASP.NET, avec une barre de navigation, un texte de présentation et des sections consacrées à la prise en main, aux bibliothèques et à l’hébergement web.

Revenez maintenant à Visual Studio et cliquez sur le fichier Dockerfile :

Explorateur de solutions de Visual Studio affichant un projet WebFormsApp, avec le Dockerfile mis en évidence.

Le fichier Dockerfile s’ouvre. Il configure votre projet pour qu’il s’exécute dans un conteneur.

Éditeur Visual Studio affichant un Dockerfile pour une application ASP.NET, avec une image de base .NET Framework, un argument source, un répertoire de travail et une commande de publication

L’instruction FROM initialise une nouvelle étape de build et définit l’image de base pour les instructions suivantes. Ici, l’image est aspnet:4.8-windowsservercore-ltsc2019, que Docker récupère dans le dépôt d’images de Microsoft.

Bien sûr, il est plus probable que votre projet Web Forms n’ait pas été créé au départ avec la prise en charge de Docker. Pour simuler cette situation, créez un nouveau projet ASP.NET Web Forms, mais cette fois sans prise en charge de Docker :

Explorateur de solutions Visual Studio affichant une solution WebFormsApp avec les fichiers du projet WebFormsAppNoDocker, notamment des pages ASPX et des fichiers de configuration.

Ajoutons maintenant un Dockerfile au nouveau projet. Faites un clic droit sur le nom du projet, choisissez le menu Add, puis le sous-menu Docker Support :

Explorateur de solutions de Visual Studio affichant le menu Ajouter, avec l’option Prise en charge de Docker sélectionnée pour un projet web

Visual Studio crée alors automatiquement le Dockerfile du projet.

Explorateur de solutions de Visual Studio affichant le projet WebFormsAppNoDocker, avec son Dockerfile sélectionné

Notez que Visual Studio a déjà sélectionné l’image et le chemin du code source à partir desquels le conteneur sera généré.

Éditeur Visual Studio affichant un Dockerfile avec une image de base ASP.NET Framework, WORKDIR /inetpub/wwwroot et une commande COPY pour copier les fichiers de sortie de la compilation

Votre projet bénéficie dès lors de la prise en charge et des avantages inhérents à la conteneurisation avec Docker : portabilité, agilité, livraison plus rapide, sécurité renforcée et gestion simplifiée.

Réduisez autant que possible la taille des images de conteneur

Les conteneurs Linux et Windows proposent des images de base légères, qui ne contiennent que les applications et les services nécessaires au fonctionnement de votre application. Une image légère avec un minimum de dépendances réduit le nombre de vulnérabilités susceptibles d’être introduites par ces dépendances, et donc la surface d’attaque.

Voyons quelques images de base que les développeurs .NET peuvent envisager pour créer des conteneurs légers. Tout d’abord, si vous utilisez encore ASP.NET Framework 4.x, qui n’est pas pris en charge sous Linux, les conteneurs Windows sont votre seule option. Microsoft recommande les images de base légères Windows Server Core et Nano Server.

Windows Server Core est un système d’exploitation minimal piloté par ligne de commande, destiné à assurer les rôles Windows Server et à exécuter des applications qui n’ont pas besoin de l’interface graphique Windows standard. Nano Server est un système d’exploitation optimisé pour les clouds privés et les centres de données. Nano Server ne permet pas de se connecter localement, est plus léger et redémarre beaucoup plus vite que Server Core.

Pour .NET Core et .NET 5+, les images SDK doivent être utilisées uniquement pour le build, tandis que les images d’exécution sont destinées aux déploiements en production dans le cadre d’un build à plusieurs étapes. Parmi les images de base légères adaptées, citons Debian bullseye-slim-amd64 et Alpine Linux.

Nous pouvons alléger encore les images de base en utilisant des images contenant les dépendances d’exécution .NET et en créant notre application .NET en mode autonome : nous ne récupérons ainsi que les dépendances dont notre application a besoin, sans rien de plus.

Mettons en pratique la création d’une application web .NET 6 avec des images légères. Ouvrez Visual Studio 2022, cliquez sur Create New Project, puis sélectionnez le type ASP.NET Core Web App.

Explorateur de solutions de Visual Studio affichant un projet WebApp avec les services connectés, les dépendances, les propriétés, wwwroot, Pages, appsettings.json, Dockerfile et C#

Donnez un nom au projet, par exemple WebApp.

Écran « Configurer votre nouveau projet » de Visual Studio affichant le nom et l’emplacement d’un projet d’application web ASP.NET Core, le nom de la solution et l’option de répertoire.

Cliquez sur Next et sélectionnez les options suivantes :

  • Framework .NET 6.0

  • Type d’authentification : Aucun

  • Configurer HTTPS : coché

  • Activer Docker : coché

  • Système d’exploitation Docker : Linux

Paramètres supplémentaires pour une application web ASP.NET Core : .NET 6.0, aucune authentification, HTTPS et Docker activés, et Linux sélectionné.

Cliquez sur le bouton Create et observez le nouveau projet dans Visual Studio.

Fenêtre de recherche de modèles affichant un modèle d’application web ASP.NET Core avec des filtres pour C#, toutes les plateformes et le Web.

Appuyez maintenant sur F5 pour exécuter l’application web hébergée dans votre conteneur Docker local.

Page d’accueil d’une application web affichant le titre « Bienvenue », un lien sur la création d’applications web avec ASP.NET Core et des liens de navigation vers Accueil et Confidentialité.

Exécutez maintenant la commande docker images pour obtenir la liste des images Docker de votre système :

> docker images

Cette commande renvoie un résultat similaire à celui-ci :

REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
webapp       dev       e3b51b1eef08   4 hours ago   208MB

Notez que l’application s’exécute dans un conteneur Linux et que l’image webapp ci-dessus fait 208 Mo.

Réduisons maintenant la taille de l’image du conteneur de notre application web.

Arrêtez l’application dans Visual Studio et ouvrez le fichier Dockerfile. Vous verrez le bloc suivant, qui indique à Docker de récupérer les images dotnet/aspnet:6.0 et dotnet/sdk:6.0 dans Microsoft Container Registry (mcr), puis de les utiliser comme images de base pour le conteneur de votre application :

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["WebApp/WebApp.csproj", "WebApp/"]
RUN dotnet restore "WebApp/WebApp.csproj"
COPY . .
WORKDIR "/src/WebApp"
RUN dotnet build "WebApp.csproj" -c Release -o /app/build

Appuyez ensuite sur F5 pour relancer l’application. Une fois l’application web démarrée, exécutez la commande docker images pour obtenir la liste des images Docker de votre système :

> docker images

La liste de vos images ressemblera à ceci :

REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
webapp       dev       778bcd52f366   4 hours ago   100MB
<none>       <none>    e3b51b1eef08   4 hours ago   208MB

Notez que l’image webapp a été reconstruite et qu’elle fait désormais 100 Mo, soit 108 Mo de moins que l’image d’origine.

Analysez les images pour détecter les vulnérabilités

Mettre régulièrement à jour la base de code constitue en soi une bonne pratique. Parmi les avantages les plus évidents : l’accès à de nouvelles fonctionnalités, aux corrections de bugs, à une meilleure interface utilisateur et à des performances améliorées. Mais les mises à jour de sécurité sont tout aussi importantes.

Le système d’exploitation ou les bibliothèques de l’image de base peuvent présenter des vulnérabilités non corrigées. Les scripts, le code et les applications ajoutés à cette image peuvent également contenir des vulnérabilités que nous ne voulons pas déployer par inadvertance en production.

L’analyse des conteneurs à la recherche de vulnérabilités est indispensable pour évaluer les risques de sécurité potentiels et prendre les mesures qui s’imposent. Pour cet exemple, choisissons une ancienne image .NET : mcr.microsoft.com/dotnet/core/aspnet:2.2.

dotnet new webapp -n "AspNet2.2" -f "netcoreapp2.2"

Ouvrons le projet dans Visual Studio et ajoutons un Dockerfile au nouveau projet. Faites un clic droit sur le nom du projet, choisissez le menu Add, puis cliquez sur le sous-menu Docker Support.

Ouvrez maintenant le fichier Dockerfile et remplacez son contenu par le code suivant :

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:2.2.105 AS build
WORKDIR /src
COPY ["AspNet2.2.csproj", "."]
RUN dotnet restore "./AspNet2.2.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "AspNet2.2.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "AspNet2.2.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AspNet2.2.dll"]

Voyons maintenant comment analyser une image pour découvrir les vulnérabilités de notre conteneur. Commencez par exécuter la commande CLI docker images pour répertorier vos images locales actuelles :

docker images

REPOSITORY       TAG       IMAGE ID       CREATED              SIZE
aspnet22         latest    223b485f4516   About a minute ago   265MB

Exécutez ensuite la commande snyk auth pour vous authentifier auprès de Snyk CLI :

> snyk auth

Une fois votre compte authentifié, vous pouvez utiliser Snyk CLI. Exécutons la commande snyk container test <repository>:<tag> pour analyser l’image créée localement et disponible dans notre daemon Docker local :

> snyk container test aspnet22:latest
Terminal PowerShell répertoriant des vulnérabilités de gravité élevée dans les paquets zlib, systemd et shadow/passwd

La commande snyk container test génère une liste des composants installés dans l’image, l’envoie au service Snyk, puis renvoie la liste des vulnérabilités présentes dans notre image.

Au final, l’analyse de l’image a détecté 193 vulnérabilités :

Rapport du terminal pour docker-image|aspnet22 indiquant 193 vulnérabilités, dont 10 critiques, dans l’image de base Microsoft .NET.

Pour surveiller l’image, exécutez la commande snyk container monitor <repository>:<tag> :

> snyk container monitor aspnet22:latest
Sortie du terminal montrant la surveillance par Snyk de l’image Docker aspnet22:latest et un lien pour consulter l’historique du projet.

La commande snyk container monitor génère une liste des composants installés dans l’image, l’envoie au service Snyk et renvoie un lien vers le service Snyk à l’adresse http://app.snyk.io/org/{YOUR-ACCOUNT}/, où vous pouvez consulter les résultats :

Tableau intitulé « Recommandations pour la mise à niveau de l’image de base », comparant les images de base .NET actuelles et alternatives selon les vulnérabilités et leur gravité.

Nos 3 meilleurs conseils pour la conteneurisation

Nous avons vu les nombreux avantages que la conteneurisation des applications .NET présente pour les développeurs et les ingénieurs DevOps. Toutefois, les conteneurs ne sont pas une solution miracle à tous les problèmes. Nous devons toujours appliquer certaines bonnes pratiques pour démystifier les conteneurs et savoir comment en tirer le meilleur parti.

Malgré l’idée reçue persistante selon laquelle les conteneurs sont réservés aux applications .NET Core, nous avons vu qu’ils peuvent également profiter aux applications .NET Framework 4.x.

Pour la taille des images de conteneur, plus elles sont petites, mieux c’est. Nous avons heureusement appris que certaines images de base sont suffisamment légères pour ne contenir que le nécessaire à l’exécution de notre application, tout en réduisant la surface d’attaque du conteneur.

Enfin, nous avons vu comment atténuer les risques de sécurité en analysant les images de conteneur et en les maintenant à jour. Les commandes Snyk container test et Snyk container monitor sont des outils précieux pour analyser nos conteneurs .NET et les surveiller en continu afin d’y détecter les vulnérabilités. Utilisée correctement, la conteneurisation peut apporter une couche supplémentaire de sécurité et de flexibilité à nos applications, quel que soit leur âge.

La sécurité des conteneurs, pensée pour les développeurs

Snyk détecte et corrige automatiquement les vulnérabilités dans les images de conteneurs et les workloads Kubernetes.