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 surtrue
. Cette propriété est implicitement définie surtrue
pour les types de projet exécutables, tels queconsole
,webapp
etworker
. EnableSdkContainerSupport
: défini surtrue
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
- Auxiliaires d’informations d’identification
- trousseau de clés système
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 PATH
de 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 , SelfContained ou 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 |