Conteneuriser une application .NET avec dotnet publish

Les conteneurs ont de nombreuses fonctionnalités et divers avantages : une infrastructure immuable qui fournit une architecture portable et permet 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 apprendre à conteneuriser une application .NET à l’aide de la commande dotnet publish.

Prérequis

Installez les éléments requis suivants :

En plus de ces prérequis, il est recommandé de vous familiariser avec les Services Worker dans .NET.

Créer une application .NET

Vous avez besoin d’une application .NET à conteneuriser. Commencez donc par créer une application à partir d’un modèle. Ouvrez votre terminal, créez un dossier de travail (sample-directory) si vous ne l’avez pas déjà fait et modifiez les répertoires afin de vous y trouver. Dans le dossier de travail, exécutez la commande suivante pour créer un projet dans un sous-répertoire nommé Worker :

dotnet new worker -o Worker -n DotNet.ContainerImage

Votre arborescence de dossiers doit ressembler à ce qui suit :

📁 sample-directory
    └──📂 Worker
        ├──appsettings.Development.json
        ├──appsettings.json
        ├──DotNet.ContainerImage.csproj
        ├──Program.cs
        ├──Worker.cs
        └──📂 obj
            ├── DotNet.ContainerImage.csproj.nuget.dgspec.json
            ├── DotNet.ContainerImage.csproj.nuget.g.props
            ├── DotNet.ContainerImage.csproj.nuget.g.targets
            ├── project.assets.json
            └── project.nuget.cache

La commande dotnet new crée un dossier nommé Worker et génère un service Worker qui, lors de l’exécution, enregistre un message toutes les secondes. À partir de votre session de terminal, modifiez les répertoires et accédez au dossier Worker. Utilisez la commande dotnet run pour démarrer l’application.

dotnet run
Building...
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:00 -05:00
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: .\Worker
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:01 -05:00
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:02 -05:00
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:03 -05:00
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
Attempting to cancel the build...

Le modèle Worker effectue une boucle indéfiniment. Utilisez la commande Annuler Ctrl+C pour l’arrêter.

Ajouter un package NuGet

Le package NuGet Microsoft.NET.Build.Containers est actuellement nécessaire pour publier un projet non-web en tant que conteneur. Pour ajouter le package NuGet Microsoft.NET.Build.Containers au modèle Worker, exécutez la commande dotnet add package suivante :

dotnet add package Microsoft.NET.Build.Containers

Conseil

Si vous créez une application web et que vous utilisez le kit de développement logiciel (SDK) .NET 7.0.300 ou une version supérieure à celle du package n’est pas obligatoire, le kit de développement logiciel (SDK) dispose des mêmes fonctionnalités prêtes à l’emploi.

Définir le nom de l’image conteneur

Différentes options de configuration sont disponibles lors de la publication d’une application en tant que conteneur.

Par défaut, le nom de l’image conteneur est le AssemblyName du projet. Si ce nom n’est pas valide comme nom d’image conteneur, vous pouvez le remplacer en spécifiant un ContainerRepository, comme indiqué dans le fichier projet suivant :

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UserSecretsId>dotnet-DotNet.ContainerImage-2e40c179-a00b-4cc9-9785-54266210b7eb</UserSecretsId>
    <ContainerRepository>dotnet-worker-image</ContainerRepository>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
  </ItemGroup>
</Project>

Pour plus d’informations, consultez ContainerRepository.

Par défaut, le nom de l’image conteneur est le AssemblyName du projet. Si ce nom n’est pas valide comme nom d’image conteneur, vous pouvez le remplacer en spécifiant un ContainerImageName (obsolète) ou le ContainerRepository préféré, comme indiqué dans le fichier projet suivant :

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UserSecretsId>dotnet-DotNet.ContainerImage-2e40c179-a00b-4cc9-9785-54266210b7eb</UserSecretsId>
    <ContainerImageName>dotnet-worker-image</ContainerImageName>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
    <PackageReference Include="Microsoft.NET.Build.Containers" Version="7.0.401" />
  </ItemGroup>
</Project>

Pour plus d’informations, consultez ContainerImageName.

Publier une application .NET

Pour publier l’application .NET en tant que conteneur, utilisez la commande dotnet publish suivante :

dotnet publish --os linux --arch x64 /t:PublishContainer -c Release

La commande CLI .NET précédente publie l’application en tant que conteneur :

  • Ciblage de Linux en tant que système d’exploitation (--os linux).
  • Spécification d’une architecture x64 (--arch x64).
  • Utilisation de la configuration de mise en production (-c Release).

Important

Pour générer le conteneur localement, vous devez avoir le démon Docker en cours d’exécution. S’il n’est pas en cours d’exécution lorsque vous tentez de publier l’application en tant que conteneur, vous rencontrerez une erreur similaire à ce qui suit :

..\build\Microsoft.NET.Build.Containers.targets(66,9): error MSB4018:
   The "CreateNewImage" task failed unexpectedly. [..\Worker\DotNet.ContainerImage.csproj]

Conseil

Selon le type d’application que vous conteneurisez, les commutateurs de ligne de commande (options) peuvent varier. Par exemple, l’argument /t:PublishContainer n’est requis que pour les applications .NET non web, comme les modèles console et worker. Pour les modèles web, remplacez l’argument /t:PublishContainer par -p:PublishProfile=DefaultContainer. Pour plus d’informations, consultez Builds de conteneur du SDK .NET, problème n° 141.

La commande génère des sorties qui ressemblent à l’exemple suivant :

Determining projects to restore...
  All projects are up-to-date for restore.
  DotNet.ContainerImage -> .\Worker\bin\Release\net8.0\linux-x64\DotNet.ContainerImage.dll
  DotNet.ContainerImage -> .\Worker\bin\Release\net8.0\linux-x64\publish\
  Building image 'dotnet-worker-image' with tags latest on top of base image mcr.microsoft.com/dotnet/aspnet:8.0
  Pushed container 'dotnet-worker-image:latest' to Docker daemon
Determining projects to restore...
  All projects are up-to-date for restore.
  DotNet.ContainerImage -> .\Worker\bin\Release\net7.0\linux-x64\DotNet.ContainerImage.dll
  DotNet.ContainerImage -> .\Worker\bin\Release\net7.0\linux-x64\publish\
  Building image 'dotnet-worker-image' with tags 1.0.0 on top of base image mcr.microsoft.com/dotnet/aspnet:7.0
  Pushed container 'dotnet-worker-image:1.0.0' to Docker daemon

Cette commande compile votre application Worker dans le dossier publish et envoie le conteneur à votre registre Docker local.

Configurer l’image conteneur

Vous pouvez contrôler de nombreux aspects du conteneur généré via les propriétés MSBuild. En général, si vous pouvez utiliser une commande dans un Dockerfile pour définir une configuration, vous pouvez en faire de même via MSBuild.

Remarque

Les seules exceptions à ce problème sont les commandes RUN. En raison de la façon dont les conteneurs sont générés, vous ne pouvez pas les émuler. Si vous avez besoin de cette fonctionnalité, vous devez utiliser un Dockerfile pour générer vos images conteneur.

ContainerArchiveOutputPath

À compter de .NET 8, vous pouvez créer un conteneur directement en tant qu’archive tar.gz. Cette fonctionnalité est utile si votre workflow n’est pas simple et vous oblige, par exemple, à exécuter un outil d’analyse sur vos images avant de les envoyer (push). Une fois l’archive créée, vous pouvez la déplacer, l’analyser ou la charger dans une chaîne d’outils Docker locale.

Pour publier dans une archive, ajoutez la propriété ContainerArchiveOutputPath à votre commande dotnet publish, par exemple :

dotnet publish \
  -p PublishProfile=DefaultContainer \
  -p ContainerArchiveOutputPath=./images/sdk-container-demo.tar.gz

Vous pouvez spécifier un nom de dossier ou un chemin d’accès avec un nom de fichier spécifique. Si vous spécifiez le nom du dossier, le nom de fichier généré pour le fichier d’archive d’images sera $(ContainerRepository).tar.gz. Ces archives peuvent contenir plusieurs étiquettes à l’intérieur, car un seul fichier est créé pour toutes les ContainerImageTags.

Configuration du nommage des images conteneur

Les images conteneur suivent une convention de nommage spécifique. Le nom de l’image est composé de plusieurs parties : registre, port facultatif, référentiel et étiquette et famille facultatives.

REGISTRY[:PORT]/REPOSITORY[:TAG[-FAMILY]]

Par exemple, prenez le nom complet de l’image mcr.microsoft.com/dotnet/runtime:8.0-alpine :

  • mcr.microsoft.com est le registre (qui représente ici le registre de conteneurs Microsoft).
  • dotnet/runtime est le référentiel (mais certains considèrent cela le user/repository).
  • 8.0-alpine est l’étiquette et la famille (la famille est un spécificateur facultatif qui permet de lever l’ambiguïté de l’empaquetage du système d’exploitation).

Certaines propriétés décrites dans les sections suivantes correspondent à la gestion des parties du nom de l’image généré. Regardez le tableau suivant qui établit la relation entre le nom de l’image et les propriétés de build :

Partie du nom de l’image Propriété MSBuild Exemples de valeurs
REGISTRY[:PORT] ContainerRegistry mcr.microsoft.com:443
PORT ContainerPort :443
REPOSITORY ContainerRepository dotnet/runtime
TAG ContainerImageTag 8.0
FAMILY ContainerFamily -alpine
Partie du nom de l’image Propriété MSBuild Exemples de valeurs
REGISTRY[:PORT] ContainerRegistry mcr.microsoft.com:443
PORT ContainerPort :443
REPOSITORY ContainerImageName dotnet/runtime
TAG ContainerImageTag 8.0

Les sections suivantes décrivent les différentes propriétés qui peuvent être utilisées pour contrôler l’image conteneur générée.

ContainerBaseImage

La propriété d’image de base de conteneur contrôle l’image utilisée comme base de votre image. Par défaut, les valeurs suivantes sont déduites en fonction des propriétés de votre projet :

  • Si votre projet est autonome, l’image mcr.microsoft.com/dotnet/runtime-deps est utilisée comme image de base.
  • Si votre projet est un projet ASP.NET Core, l’image mcr.microsoft.com/dotnet/aspnet est utilisée comme image de base.
  • Sinon, l’image mcr.microsoft.com/dotnet/runtime est utilisée comme image de base.

L’étiquette de l’image est déduite comme étant le composant numérique du TargetFramework de votre choix. Par exemple, un projet ciblant net6.0 entraîne l’étiquette 6.0 de l’image de base déduite, et un projet net7.0-linux utilisera l’étiquette 7.0, etc.

Si vous définissez une valeur ici, vous devez définir le nom complet de l’image à utiliser comme base, y compris toute étiquette de votre choix :

<PropertyGroup>
    <ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:8.0</ContainerBaseImage>
</PropertyGroup>
<PropertyGroup>
    <ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:7.0</ContainerBaseImage>
</PropertyGroup>

ContainerFamily

À partir de .NET 8, vous pouvez utiliser la propriété MSBuild ContainerFamily pour choisir une autre famille d’images conteneur fournies par Microsoft comme image de base pour votre application. Une fois définie, cette valeur est ajoutée à la fin de l’étiquette spécifique au TFM sélectionnée, en modifiant l’étiquette fournie. Par exemple, pour utiliser les variantes Alpine Linux des images de base .NET, vous pouvez définir ContainerFamily sur alpine :

<PropertyGroup>
    <ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>

La configuration du projet précédent entraîne une étiquette finale 8.0-alpine pour une application cible .NET 8.

Ce champ est libre et peut souvent être utilisé pour sélectionner différentes distributions de système d’exploitation, configurations de package par défaut ou toute autre saveur des modifications apportées à une image de base. Ce champ est ignoré quand ContainerBaseImage est défini. Pour plus d’informations, consultez Images conteneur .NET.

ContainerRuntimeIdentifier

La propriété d’identificateur du runtime de conteneur contrôle le système d’exploitation et l’architecture utilisés par votre conteneur si votre ContainerBaseImage prend en charge plusieurs plateformes. Par exemple, l’image mcr.microsoft.com/dotnet/runtime prend actuellement en charge les images linux-x64, linux-arm, linux-arm64 et win10-x64 toutes derrière la même balise. Par conséquent, les outils ont besoin d’un moyen de savoir quelle version de ces versions vous envisagez d’utiliser. Par défaut, ce paramètre est défini sur la valeur du RuntimeIdentifier que vous avez choisi lors de la publication du conteneur. Cette propriété a rarement besoin d’être définie explicitement. Utilisez plutôt l’option -r de la dotnet publish commande. Si l’image que vous avez choisie ne prend pas en charge le RuntimeIdentifier que vous avez choisi, vous obtenez une erreur qui décrit les RuntimeIdentifiers pris en charge par l’image.

Vous pouvez toujours définir la propriété ContainerBaseImage sur un nom d’image complet, y compris la balise, pour éviter d’avoir à utiliser cette propriété.

<PropertyGroup>
    <ContainerRuntimeIdentifier>linux-arm64</ContainerRuntimeIdentifier>
</PropertyGroup>

Pour plus d’informations sur les identificateurs d’exécution pris en charge par .NET, consultez le catalogue RID.

ContainerRegistry

La propriété de registre de conteneurs contrôle le registre de destination, l’emplacement vers lequel l’image nouvellement créée sera envoyée. Par défaut, elle est envoyée (push) au démon Docker local, mais vous pouvez également spécifier un registre distant. Lorsque vous utilisez un registre distant qui nécessite une authentification, vous vous authentifiez à l’aide des mécanismes connus docker login. Pour plus d’informations, consultez Authentification auprès des registres de conteneurs. Pour obtenir un exemple concret d’utilisation de cette propriété, considérez l’exemple XML suivant :

<PropertyGroup>
    <ContainerRegistry>registry.mycorp.com:1234</ContainerRegistry>
</PropertyGroup>

Cet outil prend en charge la publication sur n’importe quel registre qui prend en charge l’API Docker Registry HTTP V2. Cela inclut explicitement les registres suivants (et probablement beaucoup plus implicitement) :

Pour obtenir des notes sur l’utilisation de ces registres, consultez les notes spécifiques au registre.

ContainerRepository

Le référentiel de conteneur est le nom de l’image elle-même, par exemple dotnet/runtime ou my-app. Par défaut, le AssemblyName du projet est utilisé.

<PropertyGroup>
    <ContainerRepository>my-app</ContainerRepository>
</PropertyGroup>

ContainerImageName

Le nom de l’image conteneur contrôle le nom de l’image elle-même, par exemple dotnet/runtime ou my-app. Par défaut, le AssemblyName du projet est utilisé.

<PropertyGroup>
    <ContainerImageName>my-app</ContainerImageName>
</PropertyGroup>

Remarque

À compter de .NET 8, ContainerImageName est déconseillé en faveur de ContainerRepository.

Les noms d’image se composent d’un ou plusieurs segments délimités par des barres obliques, chacun pouvant contenir uniquement des caractères alphanumériques minuscules, des points, des traits de soulignement et des tirets, et doit commencer par une lettre ou un nombre. Tous les autres caractères entraînent la levée d’une erreur.

ContainerImageTag(s)

La propriété d’étiquette d’image conteneur contrôle les étiquettes générées pour l’image. Pour spécifier une seule utilisation d’étiquette ContainerImageTag et pour plusieurs étiquettes, utilisez ContainerImageTags.

Important

Lorsque vous utilisez ContainerImageTags, vous obtenez plusieurs images, une par étiquette unique.

Les étiquettes sont souvent utilisées pour faire référence à différentes versions d’une application, mais elles peuvent également faire référence à différentes distributions de système d’exploitation, voire à différentes configurations.

À partir de .NET 8, lorsqu’une étiquette n’est pas fournie, la valeur par défaut est latest.

Par défaut, le Version du projet est utilisé comme valeur d’étiquette.

Pour remplacer la valeur par défaut, spécifiez l’une des options suivantes :

<PropertyGroup>
    <ContainerImageTag>1.2.3-alpha2</ContainerImageTag>
</PropertyGroup>

Pour spécifier plusieurs étiquettes, utilisez un ensemble d’étiquettes délimitées par des points-virgules dans la propriété ContainerImageTags, comme lorsque vous définissez plusieurs TargetFrameworks :

<PropertyGroup>
    <ContainerImageTags>1.2.3-alpha2;latest</ContainerImageTags>
</PropertyGroup>

Les étiquettes peuvent contenir jusqu’à 127 caractères alphanumériques, points, traits de soulignement et tirets. Elles doivent commencer par un caractère alphanumérique ou un trait de soulignement. Toute autre forme entraîne la levée d’une erreur.

Remarque

Lors de l’utilisation de ContainerImageTags, les étiquettes sont délimitées par un caractère ;. Si vous appelez dotnet publish à partir de la ligne de commande (comme c’est le cas avec la plupart des environnements CI/CD), vous devez inclure les valeurs dans un wrapper unique ' et interne avec des quotes doubles ", par exemple (='"tag-1;tag-2"'). Prenons le commande dotnet publish suivante :

dotnet publish -p ContainerImageTags='"1.2.3-alpha2;latest"'

Cela entraîne la génération de deux images : my-app:1.2.3-alpha2 et my-app:latest.

Conseil

Si vous rencontrez des problèmes avec la propriété ContainerImageTags, envisagez de définir une variable d’environnement ContainerImageTags à la place :

ContainerImageTags='1.2.3;latest' dotnet publish

ContainerLabel

L’étiquette du conteneur ajoute une étiquette de métadonnées au conteneur. Les étiquettes n’ont aucun impact sur le conteneur au moment de l’exécution, mais elles sont souvent utilisées pour stocker les métadonnées de version et de création à utiliser par les analyseurs de sécurité et d’autres outils d’infrastructure. Vous pouvez spécifier n’importe quel nombre d’étiquettes de conteneur.

Le nœud ContainerLabel a deux attributs :

  • Include : clé de l’étiquette.
  • Value : valeur de l’étiquette (elle peut être vide).
<ItemGroup>
    <ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>

Pour obtenir la liste des étiquettes créées par défaut, consultez Étiquettes de conteneur par défaut.

Configurer l’exécution du conteneur

Pour contrôler l’exécution du conteneur, vous pouvez utiliser les propriétés MSBuild suivantes.

ContainerWorkingDirectory

Le nœud du répertoire de travail du conteneur contrôle le répertoire de travail du conteneur, le répertoire dans lequel les commandes sont exécutées si aucune autre commande n’est exécutée.

Par défaut, la valeur du répertoire /app est utilisée comme répertoire de travail.

<PropertyGroup>
    <ContainerWorkingDirectory>/bin</ContainerWorkingDirectory>
</PropertyGroup>

ContainerPort

Le port de conteneur ajoute des ports TCP ou UDP à la liste des ports connus pour le conteneur. Cela permet aux runtimes de conteneur comme Docker de mapper automatiquement ces ports à la machine hôte. Il est souvent utilisé comme documentation pour le conteneur, mais peut également être utilisé pour activer le mappage automatique des ports.

Le nœud ContainerPort a deux attributs :

  • Include : numéro de port à exposer.
  • Type : la valeur par défaut est tcp ; les valeurs valides sont tcp ou udp.
<ItemGroup>
    <ContainerPort Include="80" Type="tcp" />
</ItemGroup>

À partir de .NET 8, ContainerPort est déduite lorsqu’elle n’est pas fournie explicitement en fonction de plusieurs variables d’environnement ASP.NET connues :

  • ASPNETCORE_URLS
  • ASPNETCORE_HTTP_PORTS
  • ASPNETCORE_HTTPS_PORTS

Si ces variables d’environnement sont présentes, leurs valeurs sont analysées et converties en mappages de ports TCP. Ces variables d’environnement sont lues à partir de votre image de base, le cas échéant, ou à partir des variables d’environnement définies dans votre projet via les éléments ContainerEnvironmentVariable. Pour plus d’informations, consultez ContainerEnvironmentVariable.

ContainerEnvironmentVariable

Le nœud de variable d’environnement de conteneur vous permet d’ajouter des variables d’environnement au conteneur. Les variables d’environnement sont accessibles immédiatement à l’application en cours d’exécution dans le conteneur et sont souvent utilisées pour modifier le comportement d’exécution de l’application en cours d’exécution.

Le nœud ContainerEnvironmentVariable a deux attributs :

  • Include : Nom de la variable d’environnement.
  • Value : Valeur de la variable d’environnement.
<ItemGroup>
  <ContainerEnvironmentVariable Include="LOGGER_VERBOSITY" Value="Trace" />
</ItemGroup>

Pour plus d’informations, consultez Variables d’environnement .NET.

Configurer des commandes de conteneur

Par défaut, les outils de conteneur lancent votre application à l’aide du fichier binaire AppHost généré pour votre application (si votre application utilise un AppHost) ou de la commande dotnet plus la DLL de votre application.

Toutefois, vous pouvez contrôler la façon dont votre application est exécutée à l’aide d’une combinaison de ContainerAppCommand, ContainerAppCommandArgs, ContainerDefaultArgset ContainerAppCommandInstruction.

Ces différents points de configuration existent car différentes images de base utilisent différentes combinaisons du conteneur ENTRYPOINT et des propriétés COMMAND, et vous souhaitez pouvoir les prendre en charge. Les valeurs par défaut doivent être utilisables pour la plupart des applications, mais si vous souhaitez personnaliser le comportement de lancement de votre application, vous devez :

  • Identifier le fichier binaire à exécuter et le définir comme ContainerAppCommand
  • Identifier les arguments requis pour que votre application s’exécute et les définir comme ContainerAppCommandArgs
  • Identifier les arguments facultatifs (le cas échéant) et qui peuvent être remplacés par un utilisateur et les définir comme ContainerDefaultArgs
  • Paramétrez ContainerAppCommandInstruction sur DefaultArgs

Pour plus d’informations, consultez les éléments de configuration suivants.

ContainerAppCommand

L’élément de configuration de la commande d’application est le point d’entrée logique de votre application. Pour la plupart des applications, il s’agit d’AppHost, le fichier binaire exécutable généré pour votre application. Si votre application ne génère pas d’AppHost, cette commande est généralement dotnet <your project dll>. Ces valeurs sont appliquées après n’importe quel ENTRYPOINT dans votre conteneur de base, ou directement si aucun ENTRYPOINT n’est défini.

La configuration ContainerAppCommand a une propriété Include unique, qui représente la commande, l’option ou l’argument à utiliser dans la commande entrypoint :

<ItemGroup Label="ContainerAppCommand Assignment">
  <!-- This is how you would start the dotnet ef tool in your container -->
  <ContainerAppCommand Include="dotnet" />
  <ContainerAppCommand Include="ef" />

  <!-- This shorthand syntax means the same thing, note the semicolon separating the tokens. -->
  <ContainerAppCommand Include="dotnet;ef" />
</ItemGroup>

ContainerAppCommandArgs

Cet élément de configuration d’arguments de commande d’application représente tous les arguments logiquement requis pour votre application qui doivent être appliqués à ContainerAppCommand. Par défaut, aucun n’est généré pour une application. Lorsqu’il sont présents, les arguments sont appliqués à votre conteneur lorsqu’il est exécuté.

La configuration ContainerAppCommandArgs a une propriété unique Include, qui représente l’option ou l’argument à appliquer à la commande ContainerAppCommand.

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above, 
       this would be the way to force the database to update.
  -->
  <ContainerAppCommandArgs Include="database" />
  <ContainerAppCommandArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerAppCommandArgs Include="database;update" />
</ItemGroup>

ContainerDefaultArgs

Cet élément de configuration d’arguments par défaut représente tous les arguments remplçables par l’utilisateur pour votre application. Il s’agit d’un bon moyen de fournir des valeurs par défaut que votre application peut avoir besoin d’exécuter de manière à faciliter le démarrage, mais toujours facile à personnaliser.

La configuration ContainerDefaultArgs a une propriété unique Include, qui représente l’option ou l’argument à appliquer à la commande ContainerAppCommand.

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above, 
       this would be the way to force the database to update.
  -->
  <ContainerDefaultArgs Include="database" />
  <ContainerDefaultArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerDefaultArgs Include="database;update" />
</ItemGroup>

ContainerAppCommandInstruction

La configuration des instructions de commande d’application permet de contrôler la façon dont ContainerEntrypoint, ContainerEntrypointArgs, ContainerAppCommand, ContainerAppCommandArgs, et ContainerDefaultArgs sont combinés pour former la commande finale exécutée dans le conteneur. Cela dépend considérablement de si un ENTRYPOINT est présent dans l’image de base. Cette propriété peut prendre une des trois valeurs : "DefaultArgs", "Entrypoint", ou "None".

  • Entrypoint:
    • Dans ce mode, le point d’entrée est défini par ContainerAppCommand, ContainerAppCommandArgs, et ContainerDefaultArgs.
  • None :
    • Dans ce mode, le point d’entrée est défini par ContainerEntrypoint, ContainerEntrypointArgs, et ContainerDefaultArgs.
  • DefaultArgs :
    • Il s’agit du mode le plus complexe. Si aucun des éléments ContainerEntrypoint[Args] n’est présent, ContainerAppCommand[Args] et ContainerDefaultArgs sont utilisés pour créer le point d’entrée et la commande. Le point d’entrée de l’image de base pour les images de base qui ont été codées en dur vers dotnet ou /usr/bin/dotnet est ignoré afin que vous disposiez d’un contrôle total.
    • Si ContainerEntrypoint et ContainerAppCommand sont présents, alors ContainerEntrypoint devient le point d’entrée et ContainerAppCommand devient la commande.

Remarque

Les éléments de configuration ContainerEntrypoint et ContainerEntrypointArgs sont déconseillés à partir de .NET 8.

Important

Ceci est destiné aux utilisateurs avancés, la plupart des applications n’ont pas besoin de personnaliser leur point d’entrée à ce point. Pour plus d’informations et si vous souhaitez fournir des cas d’usage pour vos scénarios, consultez GitHub : discussions sur les builds du conteneur du Kit de développement logiciel (SDK) .NET.

ContainerUser

La propriété de configuration utilisateur contrôle l’utilisateur par défaut sur lequel le conteneur s’exécute. Il est souvent utilisé pour exécuter le conteneur en tant qu’utilisateur non-racine, ce qui est une bonne pratique pour la sécurité. Il existe quelques contraintes à connaître pour cette configuration :

  • Elle peut prendre différentes formes : nom d’utilisateur, identifiant utilisateur Linux, nom du groupe, identifiant de groupe Linux, username:groupname, et autres variantes d’identifiant.
  • Il n’y a pas de vérification de l’existence de l’utilisateur ou du groupe spécifié sur l’image.
  • La modification de l’utilisateur peut modifier le comportement de l’application, en particulier en ce qui concerne les éléments tels que les autorisations du Système de fichiers.

La valeur par défaut de ce champ varie selon le TFM du projet et le système d’exploitation cible :

  • Si vous ciblez .NET 8 ou une version ultérieure et que vous utilisez les images de runtime Microsoft, alors :
    • sur Linux, l’utilisateur sans racine app est utilisé (bien qu’il soit référencé par son identifiant utilisateur)
    • sur Windows, l’utilisateur sans racine ContainerUser est utilisé
  • Sinon, aucun ContainerUser par défaut n’est utilisé
<PropertyGroup>
  <ContainerUser>my-existing-app-user</ContainerUser>
</PropertyGroup>

Conseil

La variable d’environnement APP_UID est utilisée pour définir les informations utilisateur dans votre conteneur. Cette valeur peut provenir de variables d’environnement définies dans votre image de base (comme les images Microsoft .NET) ou vous pouvez la définir vous-même via la syntaxe ContainerEnvironmentVariable.

Toutefois, vous pouvez contrôler la façon dont votre application est exécutée à l’aide de ContainerEntrypoint et ContainerEntrypointArgs.

ContainerEntrypoint

Le point d’entrée du conteneur peut être utilisé pour personnaliser le ENTRYPOINT du conteneur, qui est l’exécutable appelé au démarrage du conteneur. Par défaut, pour les builds qui créent un hôte d’application, il est défini comme ContainerEntrypoint. Pour les builds qui ne créent pas d’exécutable, le dotnet path/to/app.dll est utilisé comme ContainerEntrypoint.

Le nœud ContainerEntrypoint a un attribut unique :

  • Include : commande, option ou argument à utiliser dans la commande ContainerEntrypoint.

Par exemple, considérez l’exemple suivant de groupe d’éléments de projet .NET :

<ItemGroup Label="Entrypoint Assignment">
  <!-- This is how you would start the dotnet ef tool in your container -->
  <ContainerEntrypoint Include="dotnet" />
  <ContainerEntrypoint Include="ef" />

  <!-- This shorthand syntax means the same thing.
       Note the semicolon separating the tokens. -->
  <ContainerEntrypoint Include="dotnet;ef" />
</ItemGroup>

ContainerEntrypointArgs

Le nœud args du point d’entrée du conteneur contrôle les arguments par défaut fournis au ContainerEntrypoint. Il doit être utilisé lorsque le ContainerEntrypoint est un programme que l’utilisateur peut vouloir utiliser seul. Par défaut, aucun ContainerEntrypointArgs n’est créé en votre nom.

Le nœud ContainerEntrypointArg a un attribut unique :

  • Include : option ou argument à appliquer à la commande ContainerEntrypoint.

Considérez l’exemple suivant de groupe d’éléments de projet .NET :

<ItemGroup>
  <!-- Assuming the ContainerEntrypoint defined above,
       this would be the way to update the database by
       default, but let the user run a different EF command. -->
  <ContainerEntrypointArgs Include="database" />
  <ContainerEntrypointArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerEntrypointArgs Include="database;update" />
</ItemGroup>

Étiquettes de conteneur par défaut

Les étiquettes sont souvent utilisées pour fournir des métadonnées cohérentes sur les images conteneur. Ce package fournit certaines étiquettes par défaut pour favoriser une meilleure maintenance des images générées.

  • org.opencontainers.image.created est défini sur le format ISO 8601 du DateTime UTC actuel.

Pour plus d’informations, consultez Implémenter des étiquettes conventionnelles sur une infrastructure d’étiquettes existante.

Nettoyer les ressources

Dans cet article, vous avez publié un Worker .NET en tant qu’image conteneur. Si vous le souhaitez, supprimez cette ressource. Utilisez la commande docker images pour afficher la liste des images installées.

docker images

Considérez l’exemple de sortie suivant :

REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
dotnet-worker-image   1.0.0     25aeb97a2e21   12 seconds ago   191MB

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.

Pour supprimer l’image, copiez l’ID d’image et exécutez la commande docker image rm :

docker image rm 25aeb97a2e21

Étapes suivantes