Partager via


Vue d’ensemble de la création du conteneur du Kit de développement logiciel (SDK) .NET

Bien qu’il soit possible d'conteneuriser des applications .NET avec un Dockerfile , il existe des raisons convaincantes pour conteneuriser des applications directement avec le SDK .NET. Cet article fournit une vue d’ensemble de la fonctionnalité de création de conteneurs du Kit de développement logiciel (SDK) .NET, avec des détails relatifs à la télémétrie, aux considérations relatives à la publication, aux propriétés de build et à l’authentification auprès des registres de conteneurs.

Considérations relatives aux projets de publication

Maintenant que vous disposez d’une application .NET, vous pouvez la publier en tant que conteneur. Avant de le faire, il existe plusieurs considérations importantes à prendre en compte. Avant la version 8.0.200 du Kit de développement logiciel (SDK) .NET, vous aviez besoin du package NuGet 📦 Microsoft.NET.Build.Containers. Ce package n’est pas nécessaire pour le Kit de développement logiciel (SDK) .NET version 8.0.200 et ultérieure, car la prise en charge du conteneur est incluse par défaut.

Pour activer la publication d’une application .NET en tant que conteneur, les propriétés de build suivantes sont requises :

  • IsPublishable: définir sur true. Cette propriété est implicitement définie sur true pour les types de projet exécutables, tels que console, webappet worker.
  • EnableSdkContainerSupport: défini sur true lorsque votre type de projet est une application console.

Pour activer explicitement la prise en charge du conteneur du Kit de développement logiciel (SDK), tenez compte de l’extrait de code de fichier projet suivant :

<PropertyGroup>
  <IsPublishable>true</IsPublishable>
  <EnableSdkContainerSupport>true</EnableSdkContainerSupport>
</PropertyGroup>

Publier des commutateurs et des propriétés de build

Comme avec toutes les commandes CLI .NET, vous pouvez spécifier des propriétés MSBuild sur la ligne de commande. De nombreux formulaires de syntaxe valides sont disponibles pour fournir des propriétés, telles que :

  • /p:PropertyName=Value
  • -p:PropertyName=Value
  • -p PropertyName=Value
  • --property PropertyName=Value

Vous êtes libre d’utiliser la syntaxe que vous préférez, mais la documentation présente des exemples utilisant le formulaire -p.

Conseil

Pour résoudre les problèmes, envisagez d’utiliser les journaux MSBuild. Pour générer un fichier journal binaire (binlog), ajoutez le commutateur -bl à la commande dotnet publish. Les fichiers Binlog sont utiles pour diagnostiquer les problèmes de compilation et peuvent être ouverts dans le MSBuild Structured Log Viewer . Ils fournissent une trace détaillée du processus de génération, essentiel pour l’analyse MSBuild. Pour plus d'informations, consultez Résoudre des problèmes et créer des journaux pour MSBuild.

Publier des profils et des cibles

Lorsque vous utilisez dotnet publish, l’utilisation d’un profil avec -p PublishProfile=DefaultContainer peut définir une propriété qui fait que le SDK déclenche une autre cible après le processus de publication. Il s’agit d’un moyen indirect d’atteindre le résultat souhaité. D’autre part, l’utilisation de dotnet publish /t:PublishContainer appelle directement la cible PublishContainer, atteignant le même résultat, mais de manière plus simple.

En d’autres termes, la commande CLI .NET suivante :

dotnet publish -p PublishProfile=DefaultContainer

Ce qui définit la propriété PublishProfile sur DefaultContainer, équivaut à la commande suivante :

dotnet publish /t:PublishContainer

La différence entre les deux méthodes est que l’ancien utilise un profil pour définir la propriété, tandis que ce dernier appelle directement la cible. La raison pour laquelle il est important est que les profils soient une fonctionnalité de MSBuild et qu’ils peuvent être utilisés pour définir des propriétés d’une manière plus complexe que de les définir directement.

Un problème clé est que tous les types de projets ne prennent pas en charge les profils ou ont le même ensemble de profils disponibles. En outre, il existe une disparité dans le niveau de prise en charge des profils entre différents outils, tels que Visual Studio et l’interface CLI .NET. Par conséquent, l’utilisation de cibles est généralement une méthode plus claire et plus largement prise en charge pour obtenir le même résultat.

S’authentifier auprès des registres de conteneurs

L’interaction avec les registres de conteneurs privés nécessite l’authentification auprès de ces registres.

Docker a un modèle établi avec cela via la commande docker login, qui est un moyen d’interagir avec un fichier de configuration Docker qui contient des règles d’authentification avec des registres spécifiques. Ce fichier et les types d’authentification qu’il encode sont pris en charge par Microsoft.Net.Build.Containers pour l’authentification du Registre. Cela devrait garantir que ce package fonctionne sans problème avec n'importe quel registre depuis lequel vous pouvez docker pull et docker push. Ce fichier est normalement stocké à ~/.docker/config.json, mais il peut être spécifié en outre via la variable DOCKER_CONFIG, qui pointe vers un répertoire contenant un fichier config.json.

Types d’authentification

Le fichier config.json contient trois types d’authentification :

Nom d’utilisateur/mot de passe explicite

La section auths du fichier config.json est un mappage clé/valeur entre les noms de Registre et les chaînes nom d’utilisateur :mot de passe encodées en Base64. Dans un scénario Docker courant, l’exécution de docker login <registry> -u <username> -p <password> crée de nouveaux éléments dans cette carte. Ces informations d’identification sont populaires dans les systèmes d’intégration continue (CI), où la connexion est effectuée par des jetons au début d’une exécution. Toutefois, ils sont moins populaires pour les ordinateurs de développement des utilisateurs finaux en raison du risque de sécurité d’avoir des informations d’identification nues dans un fichier.

Auxiliaires d’informations d’identification

La section credHelpers du fichier config.json est un mappage clé/valeur entre les noms de Registre et les noms de programmes spécifiques qui peuvent être utilisés pour créer et récupérer des informations d’identification pour ce registre. Cela est souvent utilisé lorsque des registres particuliers ont des exigences d’authentification complexes. Pour que ce type d’authentification fonctionne, vous devez disposer d’une application nommée docker-credential-{name} sur le PATHde votre système. Ces types d’informations d’identification ont tendance à être sécurisés, mais peuvent être difficiles à configurer sur des machines de développement ou CI.

Trousseaux de clés système

La section credsStore est une propriété de chaîne unique dont la valeur est le nom d’un programme d’assistance d’informations d’identification Docker qui sait comment interagir avec le gestionnaire de mots de passe du système. Pour Windows, cela peut être wincred par exemple. Ils sont populaires avec les programmes d’installation Docker pour macOS et Windows.

Authentification via des variables d’environnement

Dans certains scénarios, le mécanisme d’authentification Docker standard décrit ci-dessus n’est tout simplement pas suffisant. Cet outil dispose d’un mécanisme supplémentaire pour fournir des informations d’identification aux registres : variables d’environnement. Si des variables d’environnement sont utilisées, le mécanisme de fourniture d’informations d’identification ne sera pas utilisé du tout. Les variables d’environnement suivantes sont prises en charge :

  • DOTNET_CONTAINER_REGISTRY_UNAME: il doit s’agir du nom d’utilisateur du Registre. Si le mot de passe du Registre est un jeton, le nom d’utilisateur doit être "<token>".
  • DOTNET_CONTAINER_REGISTRY_PWORD: il doit s’agir du mot de passe ou du jeton du Registre.

Remarque

À partir du Kit de développement logiciel (SDK) .NET 8.0.400, les variables d’environnement pour les opérations de conteneur ont été mises à jour. Les variables SDK_CONTAINER_* sont maintenant précédées de DOTNET_CONTAINER_*.

Ce mécanisme est potentiellement vulnérable aux fuites d’informations d’identification. Il doit donc être utilisé uniquement dans les scénarios où l’autre mécanisme n’est pas disponible. Par exemple, si vous utilisez l’outil conteneur du SDK à l’intérieur d’un conteneur Docker lui-même. De plus, ce mécanisme n’utilise pas d’espace de noms : il tente d’utiliser les mêmes informations d’identification pour le registre source (où se trouve votre image de base) et le registre de destination (où vous téléversez votre image finale).

Utilisation de registres non sécurisés

La plupart des accès au Registre sont supposés être sécurisés, ce qui signifie que HTTPS est utilisé pour interagir avec le Registre. Toutefois, tous les registres ne sont pas configurés avec des certificats TLS, en particulier dans des situations telles qu’un registre d’entreprise privé derrière un VPN. Pour prendre en charge ces cas d’usage, les outils de conteneur fournissent des moyens de déclarer qu’un registre spécifique utilise une communication non sécurisée.

À compter de .NET 8.0.400, le Kit de développement logiciel (SDK) comprend ces fichiers et formats de configuration et utilise automatiquement cette configuration pour déterminer si HTTP ou HTTPS doit être utilisé. La configuration d’un registre pour la communication non sécurisée varie en fonction de l’outil de conteneur de votre choix.

Docker

Docker stocke sa configuration de Registre dans la configuration du démon . Pour ajouter de nouveaux registres non sécurisés, de nouveaux hôtes sont ajoutés à la propriété de tableau "insecure-registries" :

{
  "insecure-registries": [
    "registry.mycorp.net"
  ]
}

Remarque

Vous devez redémarrer le démon Docker pour appliquer les modifications apportées à ce fichier.

Podman

Podman utilise un fichier TOML registries.conf pour stocker les informations de connexion du Registre. Ce fichier vit généralement à /etc/containers/registries.conf. Pour ajouter de nouveaux registres non sécurisés, une section TOML est ajoutée pour contenir les paramètres du registre, puis l’option insecure doit être définie sur true.

[[registry]]
location = "registry.mycorp.net"
insecure = true

Remarque

Vous devez redémarrer Podman pour appliquer les modifications apportées au fichier registries.conf.

Variables d’environnement

À compter de la version 9.0.100, le Kit de développement logiciel (SDK) .NET reconnaît les registres non sécurisés transmis par le biais de la variable d’environnement DOTNET_CONTAINER_INSECURE_REGISTRIES. Cette variable prend une liste séparée par des virgules de domaines pour traiter comme non sécurisés de la même manière que les exemples Docker et Podman ci-dessus.

$Env:DOTNET_CONTAINER_INSECURE_REGISTRIES=localhost:5000,registry.mycorp.com; dotnet publish -t:PublishContainer -p:ContainerRegistry=registry.mycorp.com -p:ContainerBaseImage=localhost:5000/dotnet/runtime:9.0

Télémétrie

Lorsque vous publiez une application .NET en tant que conteneur, l’outil conteneur du Kit de développement logiciel (SDK) .NET collecte et envoie des données de télémétrie d’utilisation sur la façon dont les outils sont utilisés. Les données collectées sont en plus des données de télémétrie envoyées par l’interface CLI .NET, mais utilisent les mêmes mécanismes et, surtout, adhèrent aux mêmes contrôles de refus .

Les données de télémétrie collectées sont destinées à être de nature générale et à ne pas divulguer d’informations personnelles , l’objectif prévu est de mesurer :

  • Utilisation globale de la fonctionnalité de conteneurisation du Kit de développement logiciel (SDK) .NET.
  • Taux de réussite et d’échec, ainsi que des informations générales sur les types d’échecs qui se produisent le plus fréquemment.
  • Utilisation de fonctionnalités spécifiques de la technologie, telles que la publication sur différents types de registres ou la manière dont la publication a été réalisée.

Pour désactiver la télémétrie, définissez la variable d’environnement DOTNET_CLI_TELEMETRY_OPTOUT sur true. Pour plus d’informations, veuillez consulter Télémétrie CLI .NET.

Télémétrie d’inférence

Les informations suivantes sur la façon dont le processus d’inférence d’image de base s’est produit sont journalisées :

Point de date Explication Exemple de valeur
InferencePerformed Si les utilisateurs spécifient manuellement des images de base par opposition à l'utilisation de l'inférence. true
TargetFramework Le TargetFramework choisi lors de l’inférence d’image de base. net8.0
BaseImage Valeur de l’image de base choisie, mais uniquement si cette image de base est l’une des images produites par Microsoft. Si un utilisateur spécifie une image autre que les images produites par Microsoft sur mcr.microsoft.com, cette valeur est null. mcr.microsoft.com/dotnet/aspnet
BaseImageTag Valeur de la balise choisie, mais uniquement si cette balise concerne l’une des images produites par Microsoft. Si un utilisateur spécifie une image autre que les images produites par Microsoft sur mcr.microsoft.com, cette valeur est null. 8.0
ContainerFamily Valeur de la propriété ContainerFamily si un utilisateur a utilisé la fonctionnalité ContainerFamily pour choisir une « saveur » de l’une de nos images de base. Cela est défini uniquement si l’utilisateur a choisi ou déduit l’une des images .NET produites par Microsoft à partir de mcr.microsoft.com jammy-chiseled
ProjectType Type de projet en cours de conteneurisation. AspNetCore ou Console
PublishMode Comment l’application a été empaquetée. Aot, Trimmed, SelfContainedou FrameworkDependent
IsInvariant Si l’image choisie nécessite une globalisation invariante ou si l’utilisateur l’a choisi manuellement. true
TargetRuntime RID pour lequel cette application a été publiée. linux-x64

Télémétrie de création d’images

Les informations suivantes sur la façon dont le processus de création et de publication du conteneur s’est produit sont journalisées :

Point de date Explication Exemple de valeur
RemotePullType Si l’image de base provient d’un registre distant, quel type de registre était-il ? Azure, AWS, Google, GitHub, DockerHub, MRC ou autre
LocalPullType Si l’image de base provient d’une source locale, comme un démon conteneur ou un tarball. Docker, Podman, Tarball
RemotePushType Si l’image a été envoyée à un registre distant, de quel type de registre s'agit-il ? Azure, AWS, Google, GitHub, DockerHub, MRC ou autre
LocalPushType Si l'image a été envoyée vers une destination locale, quelle était-elle ? Docker, Podman, Tarball

En outre, si différents types d'erreurs se produisent pendant le processus, des données sont collectées sur le type d'erreur survenu.

Moment précis Explication Exemple de valeur
Error Type d’erreur qui s’est produite unknown_repository, credential_failure, rid_mismatch, local_load.
Direction Si l’erreur est un credential_failure, concernait-elle un registre push ou pull ? push
RID cible Si l’erreur était un rid_mismatch, quel RID a été demandé ? linux-x64
Les RIDs disponibles Si l'erreur était un rid_mismatch, quels RID étaient pris en charge par l'image de base ? linux-x64,linux-arm64

Voir aussi