Tutoriel : Conteneuriser une application .NET
Dans ce tutoriel, vous allez apprendre à conteneuriser une application .NET avec Docker. Les conteneurs ont de nombreuses fonctionnalités et avantages, tels qu’être une infrastructure immuable, fournir une architecture portable et permettre la scalabilité. L’image vous permettra de créer des conteneurs pour votre environnement de développement local, votre cloud privé ou votre cloud public.
Dans ce tutoriel, vous allez :
- Créer et publier une application .NET simple
- Créer et configurer un fichier Dockerfile pour .NET
- Générer une image Docker
- Créer et exécuter un conteneur Docker
Vous allez comprendre les tâches de génération et de déploiement de conteneur Docker pour une application .NET. La plateforme Docker utilise le moteur Docker pour créer et empaqueter rapidement des applications en tant qu’images Docker. Ces images sont écrites au format Dockerfile pour être déployées et exécutées dans un conteneur en couches.
Notes
Ce tutoriel ne s’adresse pas aux applications ASP.NET Core. Si vous utilisez ASP.NET Core, consultez le tutoriel Apprendre à conteneuriser une application ASP.NET Core.
Prérequis
Installez les éléments requis suivants :
- Kit de développement logiciel (SDK) .NET
Si vous avez installé .NET, utilisez la commande pour déterminer ledotnet --info
Kit de développement logiciel (SDK) que vous utilisez. - Docker Community Edition
- Dossier de travail temporaire pour l’exemple d’application Dockerfile et .NET. Dans ce didacticiel, le nom docker-working est utilisé comme dossier de travail.
Créer une application .NET
Vous avez besoin d’une application .NET que le conteneur Docker exécutera. Ouvrez votre terminal, créez un dossier de travail si ce n’est déjà fait, et accédez-y. Dans le dossier de travail, exécutez la commande suivante pour créer un projet dans un sous-répertoire nommé App :
dotnet new console -o App -n DotNet.Docker
Votre arborescence de dossiers doit ressembler à ce qui suit :
📁 docker-working
└──📂 App
├──DotNet.Docker.csproj
├──Program.cs
└──📂 obj
├── DotNet.Docker.csproj.nuget.dgspec.json
├── DotNet.Docker.csproj.nuget.g.props
├── DotNet.Docker.csproj.nuget.g.targets
├── project.assets.json
└── project.nuget.cache
La dotnet new
commande crée un dossier nommé App et génère une application console « Hello World ». Modifiez les répertoires et accédez au dossier Application à partir de votre session de terminal. Utilisez la dotnet run
commande pour démarrer l’application. L’application s’exécute et s’imprime Hello World!
sous la commande :
dotnet run
Hello World!
Le modèle par défaut crée une application qui s’imprime sur le terminal, puis se termine immédiatement. Pour ce tutoriel, vous utiliserez une application qui effectue une boucle indéfiniment. Ouvrez le fichier Program.cs dans un éditeur de texte.
Conseil
Si vous utilisez Visual Studio Code, à partir de la session de terminal précédente, tapez la commande suivante :
code .
Le dossier App qui contient le projet dans Visual Studio Code s’ouvre.
Le fichier Program.cs doit ressembler au code C# suivant :
Console.WriteLine("Hello World!");
Remplacez le fichier par le code suivant qui compte les nombres chaque seconde :
var counter = 0;
var max = args.Length != 0 ? Convert.ToInt32(args[0]) : -1;
while (max == -1 || counter < max)
{
Console.WriteLine($"Counter: {++counter}");
await Task.Delay(TimeSpan.FromMilliseconds(1_000));
}
Enregistrez le fichier et effectuez un nouveau avec dotnet run
. N’oubliez pas que cette application s’exécute indéfiniment. Utilisez la commande cancel Ctrl+C pour l’arrêter. Voici un exemple de sortie :
dotnet run
Counter: 1
Counter: 2
Counter: 3
Counter: 4
^C
Si vous envoyez un nombre à l’application sur la ligne de commande, l’application comptera uniquement jusqu’à ce montant puis se fermera. Effectuez un test avec dotnet run -- 5
pour compter jusqu’à cinq.
Important
Tous les paramètres après --
sont transmis à votre application au lieu d’être transmis à la commande dotnet run
.
Publier une application .NET
Avant d’ajouter l’application .NET à l’image Docker, elle doit d’abord être publiée. Il est préférable que le conteneur exécute la version publiée de l’application. Pour publier l’application, exécutez la commande suivante :
dotnet publish -c Release
Cette commande compile votre application dans le dossier publish. Le chemin du dossier publish à partir du dossier de travail doit être .\App\bin\Release\net6.0\publish\
Dans le dossier Application , obtenez une liste de répertoires du dossier de publication pour vérifier que le fichier DotNet.Docker.dll a été créé.
dir .\bin\Release\net6.0\publish\
Directory: C:\Users\dapine\App\bin\Release\net6.0\publish
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 3/8/2022 10:43 AM 431 DotNet.Docker.deps.json
-a--- 3/8/2022 10:43 AM 6144 DotNet.Docker.dll
-a--- 3/8/2022 10:43 AM 149504 DotNet.Docker.exe
-a--- 3/8/2022 10:43 AM 10516 DotNet.Docker.pdb
-a--- 3/8/2022 10:43 AM 253 DotNet.Docker.runtimeconfig.json
Créer le Dockerfile
Le fichier Dockerfile est utilisé par la commande docker build
pour créer une image de conteneur. Ce fichier est un fichier texte nommé Dockerfile qui n’a pas d’extension.
Créez un fichier nommé Dockerfile dans le répertoire contenant le fichier .csproj et ouvrez-le dans un éditeur de texte. Ce tutoriel utilise l’image d’exécution ASP.NET Core (qui contient l’image du runtime .NET) et correspond à l’application console .NET.
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /App
# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
Notes
L’image runtime ASP.NET Core est utilisée intentionnellement ici, bien que l’image mcr.microsoft.com/dotnet/runtime:6.0
ait pu être utilisée.
Conseil
Ce Dockerfile utilise des builds multi-phases, qui optimisent la taille finale de l’image en superposant la build et en ne laissant que les artefacts requis. Pour plus d’informations, consultez Docker Docs : builds multi-phases.
Le FROM
mot clé nécessite un nom d’image conteneur Docker complet. Microsoft Container Registry (MCR, mcr.microsoft.com) est un syndicat de Docker Hub qui héberge des conteneurs accessibles publiquement. Le dotnet
segment est le référentiel de conteneurs, tandis que le sdk
segment ou aspnet
est le nom de l’image conteneur. L’image est étiquetée avec 6.0
, qui est utilisé pour le contrôle de version. Par conséquent, mcr.microsoft.com/dotnet/aspnet:6.0
est le runtime .NET 6.0. Veillez à extraire la version du runtime qui correspond au runtime ciblé par votre SDK. Par exemple, l’application créée dans la section précédente a utilisé le Kit de développement logiciel (SDK) .NET 6.0 et l’image de base référencée dans le fichier Dockerfile est marquée avec la valeur 6.0.
Enregistrez le fichier Dockerfile. La structure de répertoires du dossier de travail doit ressembler à ce qui suit. Certains des fichiers et dossiers de niveau supérieur ont été omis pour économiser de l’espace dans l’article :
📁 docker-working
└──📂 App
├── Dockerfile
├── DotNet.Docker.csproj
├── Program.cs
├──📂 bin
│ └──📂 Release
│ └──📂 net6.0
│ └──📂 publish
│ ├── DotNet.Docker.deps.json
│ ├── DotNet.Docker.exe
│ ├── DotNet.Docker.dll
│ ├── DotNet.Docker.pdb
│ └── DotNet.Docker.runtimeconfig.json
└──obj 📁
└──...
Dans votre terminal, exécutez la commande suivante :
docker build -t counter-image -f Dockerfile .
Docker traitera chaque ligne du Dockerfile. dans .
la docker build
commande définit le contexte de build de l’image. Le -f
commutateur est le chemin d’accès au fichier Dockerfile. Cette commande génère l’image et crée un dépôt local nommé counter-image qui pointe vers cette image. Une fois cette commande terminée, exécutez docker images
pour afficher une liste des images installées :
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
counter-image latest 2f15637dc1f6 10 minutes ago 208MB
Le counter-image
dépôt est le nom de l’image. La latest
balise est la balise utilisée pour identifier l’image. 2f15637dc1f6
est l’ID d’image. 10 minutes ago
correspond à l’heure à laquelle l’image a été créée. 208MB
est la taille de l’image. Les dernières étapes du Dockerfile sont de créer un conteneur à partir de l’image et d’exécuter l’application, de copier l’application publiée dans le conteneur et de définir le point d’entrée.
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
La commande COPY
indique à Docker de copier le dossier spécifié sur votre ordinateur, dans un dossier du conteneur. Dans cet exemple, le dossier de publication est copié dans un dossier nommé App dans le conteneur.
La WORKDIR
commande remplace le répertoire actif à l’intérieur du conteneur en Application.
La commande suivante, ENTRYPOINT
, indique à Docker de configurer le conteneur afin de l’exécuter comme un fichier exécutable. Au démarrage du conteneur, la commande ENTRYPOINT
s’exécute. Lorsque cette commande se termine, le conteneur s’arrête automatiquement.
Conseil
Pour plus de sécurité, vous pouvez désactiver le pipeline de diagnostic. Lorsque vous désactivez, cela permet au conteneur de s’exécuter en lecture seule. Pour ce faire, spécifiez une variable d’environnement DOTNET_EnableDiagnostics
comme 0
(juste avant l’étape ENTRYPOINT
) :
ENV DOTNET_EnableDiagnostics=0
Pour plus d’informations sur différentes variables d’environnement .NET, consultez Variables d’environnement .NET.
Notes
.NET 6 se standardise sur le préfixe DOTNET_
au lieu de pour les variables d’environnement qui configurent le comportement au moment de COMPlus_
l’exécution .NET. Toutefois, le COMPlus_
préfixe continue de fonctionner. Si vous utilisez une version précédente du runtime .NET, vous devez toujours utiliser le préfixe pour les COMPlus_
variables d’environnement.
Dans votre terminal, exécutez docker build -t counter-image -f Dockerfile .
puis, une fois la commande terminée, exécutez docker images
.
docker build -t counter-image -f Dockerfile .
[+] Building 3.1s (14/14) FINISHED
=> [internal] load build definition from Dockerfile 0.5s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.6s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/aspnet:6.0 0.8s
=> [internal] load metadata for mcr.microsoft.com/dotnet/sdk:6.0 1.1s
=> [stage-1 1/3] FROM mcr.microsoft.com/dotnet/aspnet:6.0@sha256:f1539d71 0.0s
=> [internal] load build context 0.4s
=> => transferring context: 4.00kB 0.1s
=> [build-env 1/5] FROM mcr.microsoft.com/dotnet/sdk:6.0@sha256:16e355af1 0.0s
=> CACHED [stage-1 2/3] WORKDIR /App 0.0s
=> CACHED [build-env 2/5] WORKDIR /App 0.0s
=> CACHED [build-env 3/5] COPY . ./ 0.0s
=> CACHED [build-env 4/5] RUN dotnet restore 0.0s
=> CACHED [build-env 5/5] RUN dotnet publish -c Release -o out 0.0s
=> CACHED [stage-1 3/3] COPY --from=build-env /App/out . 0.0s
=> exporting to image 0.4s
=> => exporting layers 0.0s
=> => writing image sha256:2f15637d 0.1s
=> => naming to docker.io/library/counter-image
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
counter-image latest 2f15637dc1f6 10 minutes ago 208MB
Chaque commande dans le Dockerfile a généré une couche et créé une valeur IMAGE ID. L’ID d’image final (le vôtre sera différent) est 2f15637dc1f6 et vous allez ensuite créer un conteneur basé sur cette image.
Créez un conteneur.
Maintenant que vous disposez d’une image qui contient votre application, vous pouvez créer un conteneur. Vous pouvez créer un conteneur de deux manières. Tout d’abord, créez un conteneur arrêté.
docker create --name core-counter counter-image
La docker create
commande ci-dessus crée un conteneur basé sur l’image de contre-image . La sortie de cette commande affiche l’ID CONTENEUR (le vôtre sera différent) du conteneur créé :
cf01364df4539812684c64277f5363a8fb354ef4c90785dc0845769a6c5b0f8e
Pour afficher une liste de tous les conteneurs, utilisez la commande docker ps -a
:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf01364df453 counter-image "dotnet DotNet.Docke…" 18 seconds ago Created core-counter
Gérer le conteneur
Le conteneur a été créé avec un nom core-counter
spécifique , ce nom est utilisé pour gérer le conteneur. L’exemple suivant utilise la commande docker start
pour démarrer le conteneur, puis la commande docker ps
pour afficher uniquement les conteneurs en cours d’exécution :
docker start core-counter
core-counter
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf01364df453 counter-image "dotnet DotNet.Docke…" 53 seconds ago Up 10 seconds core-counter
De même, la commande docker stop
arrêtera le conteneur. L’exemple suivant utilise la docker stop
commande pour arrêter le conteneur, puis utilise la docker ps
commande pour indiquer qu’aucun conteneur n’est en cours d’exécution :
docker stop core-counter
core-counter
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Se connecter à un conteneur
Lorsqu’un conteneur est en cours d’exécution, vous pouvez vous connecter à ce dernier pour afficher le résultat. Utilisez les commandes docker start
et docker attach
pour démarrer le conteneur et observer le flux de sortie. Dans cet exemple, la touche Ctrl+C est utilisée pour détacher du conteneur en cours d’exécution. Cette frappe met fin au processus dans le conteneur, sauf indication contraire, ce qui arrête le conteneur. Le --sig-proxy=false
paramètre garantit que Ctrl+C n’arrêtera pas le processus dans le conteneur.
Après vous être déconnecté du conteneur, reconnectez-vous pour vérifier qu’il est toujours en cours d’exécution et de comptage.
docker start core-counter
core-counter
docker attach --sig-proxy=false core-counter
Counter: 7
Counter: 8
Counter: 9
^C
docker attach --sig-proxy=false core-counter
Counter: 17
Counter: 18
Counter: 19
^C
Supprimer un conteneur
Pour cet article, vous ne voulez pas que des conteneurs traînent autour de qui ne font rien. Supprimez le conteneur que vous avez créé précédemment. Si le conteneur est en cours d’exécution, arrêtez-le.
docker stop core-counter
L’exemple suivant répertorie tous les conteneurs. Il utilise ensuite la docker rm
commande pour supprimer le conteneur, puis vérifie une deuxième fois pour tous les conteneurs en cours d’exécution.
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f6424a7ddce counter-image "dotnet DotNet.Dock…" 7 minutes ago Exited (143) 20 seconds ago core-counter
docker rm core-counter
core-counter
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Exécution unique
Docker fournit la commande docker run
pour créer et exécuter le conteneur comme une commande unique. Cette commande vous évite de devoir exécuter docker create
, puis docker start
. Vous pouvez également définir cette commande pour supprimer automatiquement le conteneur lorsque le conteneur s’arrête. Par exemple, utilisez docker run -it --rm
pour effectuer deux opérations : utiliser automatiquement le terminal actuel pour se connecter au conteneur, puis supprimer ce conteneur une fois qu’il est terminé :
docker run -it --rm counter-image
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
^C
Le conteneur transmet également des paramètres dans l’exécution de l’application .NET. Pour indiquer à l’application .NET de compter uniquement 3 pass in 3.
docker run -it --rm counter-image 3
Counter: 1
Counter: 2
Counter: 3
Avec docker run -it
, la commande Ctrl+C arrête le processus en cours d’exécution dans le conteneur, ce qui, à son tour, arrête le conteneur. Comme le paramètre --rm
a été fourni, le conteneur est automatiquement supprimé lorsque le processus est arrêté. Vérifiez qu’il n’existe pas :
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Modifier la commande ENTRYPOINT
La commande docker run
vous permet également de modifier la commande ENTRYPOINT
depuis le Dockerfile , puis d’exécuter un autre élément, mais uniquement pour ce conteneur. Par exemple, utilisez la commande suivante pour exécuter bash
ou cmd.exe
. Modifiez la commande selon vos besoins.
Dans cet exemple, ENTRYPOINT
est remplacé par cmd.exe
. Appuyez sur Ctrl+C pour mettre fin au processus et arrêter le conteneur.
docker run -it --rm --entrypoint "cmd.exe" counter-image
Microsoft Windows [Version 10.0.17763.379]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\>dir
Volume in drive C has no label.
Volume Serial Number is 3005-1E84
Directory of C:\
04/09/2019 08:46 AM <DIR> app
03/07/2019 10:25 AM 5,510 License.txt
04/02/2019 01:35 PM <DIR> Program Files
04/09/2019 01:06 PM <DIR> Users
04/02/2019 01:35 PM <DIR> Windows
1 File(s) 5,510 bytes
4 Dir(s) 21,246,517,248 bytes free
C:\>^C
Commandes essentielles
Docker a de nombreuses commandes différentes qui créent, gèrent et interagissent avec des conteneurs et des images. Ces commandes Docker sont essentielles à la gestion de vos conteneurs :
Nettoyer les ressources
Au cours de ce tutoriel, vous avez créé des conteneurs et des images. Si vous le souhaitez, supprimez ces ressources. Utilisez les commandes suivantes pour
Lister tous les conteneurs
docker ps -a
Arrêtez les conteneurs qui s’exécutent par leur nom.
docker stop counter-image
Supprimer un conteneur
docker rm counter-image
Supprimez ensuite toutes les images que vous ne souhaitez plus conserver sur votre ordinateur. Supprimez l’image créée par votre fichier Dockerfile , puis supprimez l’image .NET sur laquelle dockerfile était basé. Vous pouvez utiliser la valeur IMAGE ID ou la chaîne mise en forme REPOSITORY:TAG.
docker rmi counter-image:latest
docker rmi mcr.microsoft.com/dotnet/aspnet:6.0
Utilisez la commande docker images
pour afficher la liste des images installées.
Conseil
Les fichiers image peuvent être volumineux. En règle générale, vous supprimez les conteneurs temporaires que vous avez créés lors des tests et du développement de votre app. Vous conservez normalement les images de base avec le runtime installé si vous envisagez de créer d’autres images basées sur ce runtime.