Containerisieren einer .NET-App mit dem Befehl „dotnet publish“
Container haben viele Features und Vorteile, z. B. eine unveränderliche Infrastruktur, eine portable Architektur und die Skalierbarkeit. Das Image kann zum Erstellen von Containern für Ihre lokale Entwicklungsumgebung, eine private Cloud oder eine öffentliche Cloud verwendet werden. In diesem Tutorial erfahren Sie, wie Sie eine .NET-Anwendung mithilfe des Befehls dotnet publish containerisieren.
Voraussetzungen
Die folgenden Komponenten müssen installiert sein:
- .NET 8+ SDK
Wenn Sie .NET installiert haben, verwenden Sie den Befehldotnet --info
, um festzustellen, welches SDK Sie verwenden. - Docker Community Edition
- SDK für .NET ab Version 7
Wenn Sie .NET installiert haben, verwenden Sie den Befehldotnet --info
, um festzustellen, welches SDK Sie verwenden. - Docker Community Edition
Zusätzlich zu diesen Voraussetzungen ist es empfehlenswert, mit Workerdiensten in .NET vertraut zu sein.
Erstellen einer .NET-App
Sie benötigen eine .NET-App zum Containerisieren. Beginnen Sie daher mit dem Erstellen einer neuen App anhand einer Vorlage. Öffnen Sie Ihr Terminal, erstellen Sie einen Arbeitsordner (sample-directory), falls noch nicht geschehen, und ändern Sie die Verzeichnisse so, dass Sie sich darin befinden. Führen Sie im Arbeitsordner den folgenden Befehl aus, um ein neues Projekt im Unterverzeichnis Worker zu erstellen:
dotnet new worker -o Worker -n DotNet.ContainerImage
Ihre Ordnerstruktur sollte wie folgt aussehen:
📁 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
Mit dem Befehl dotnet new
erstellen Sie einen neuen Ordner mit dem Namen Worker und generieren einen Workerdienst, bei dessen Ausführung jede Sekunde eine Nachricht protokolliert wird. Ändern Sie in Ihrer Terminalsitzung die Verzeichnisse, und navigieren Sie zum Ordner Worker. Verwenden Sie den dotnet run
-Befehl, um die App zu starten.
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...
Die Workervorlage wird unbegrenzt in einer Schleife ausgeführt. Verwenden Sie zum Beenden den Befehl STRG+C, um diese anzuhalten.
Hinzufügen des NuGet-Pakets
Das NuGet-Paket Microsoft.NET.Build.Containers ist derzeit erforderlich, um ein Webprojekt als Container zu veröffentlichen. Zum Hinzufügen des NuGet-Pakets Microsoft.NET.Build.Containers
zur Workervorlage führen Sie den folgenden Befehl dotnet add package aus:
dotnet add package Microsoft.NET.Build.Containers
Tipp
Wenn Sie eine Webanwendung erstellen und das .NET SDK 7.0.300 oder höher verwenden, ist das Paket nicht erforderlich – die Funktionen sind bereits im SDK enthalten.
Festlegen des Namens des Containerimages
Beim Veröffentlichen einer App als Container stehen verschiedene Konfigurationsoptionen zur Verfügung.
Standardmäßig ist der Name des Containerimages der AssemblyName
des Projekts. Wenn dieser Name als Containerimagename ungültig ist, können Sie ihn überschreiben, indem Sie einen ContainerRepository
wie in der folgenden Projektdatei angeben:
<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>
Weitere Informationen finden Sie unter ContainerRepository.
Standardmäßig ist der Name des Containerimages der AssemblyName
des Projekts. Wenn dieser Name als Containerimagename ungültig ist, können Sie ihn überschreiben, indem Sie einen ContainerImageName
(veraltet) oder das bevorzugte ContainerRepository
wie in der folgenden Projektdatei angeben:
<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>
Weitere Informationen finden Sie unter ContainerImageName.
Veröffentlichen einer .NET-App
Veröffentlichen Sie die .NET-App als Container mit dem folgenden dotnet publish-Befehl:
dotnet publish --os linux --arch x64 /t:PublishContainer -c Release
Mit dem vorherigen .NET CLI-Befehl wird die App als Container veröffentlicht:
- Für Linux als Betriebssystem (
--os linux
). - Angeben einer x64-Architektur (
--arch x64
). - Verwenden der Releasekonfiguration (
-c Release
).
Wichtig
Um den Container lokal zu erstellen, muss der Docker-Daemon ausgeführt werden. Wenn dieser nicht ausgeführt wird, sobald Sie versuchen, die App als Container zu veröffentlichen, tritt ein Fehler ähnlich dem folgenden auf:
..\build\Microsoft.NET.Build.Containers.targets(66,9): error MSB4018:
The "CreateNewImage" task failed unexpectedly. [..\Worker\DotNet.ContainerImage.csproj]
Tipp
Je nach Typ der App, die Sie containerisieren, können die Befehlszeilenschalter (Optionen) variieren. Das Argument /t:PublishContainer
ist beispielsweise nur für Nicht-Web-.NET-Apps erforderlich, wie die Vorlagen console
und worker
. Ersetzen Sie bei Webvorlagen das Argument /t:PublishContainer
durch -p:PublishProfile=DefaultContainer
. Weitere Informationen finden Sie unter .NET SDK-Containerbuilds, Issue 141.
Der Befehl erzeugt eine Ausgabe ähnlich der Beispielausgabe:
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
Dieser Befehl kompiliert Ihre Worker-App in den Ordner publish und pusht den Container in Ihre lokale Docker-Registrierung.
Konfigurieren eines Containerimages
Sie können über MSBuild-Eigenschaften viele Aspekte des generierten Containers steuern. Wenn Sie einen Befehl in einer Dockerfile verwenden können, um eine Konfiguration festzulegen, ist dies in der Regel auch über MSBuild möglich.
Hinweis
Die einzigen Ausnahmen sind RUN
-Befehle. Aufgrund der Art und Weise, wie Container angelegt sind, können diese nicht emuliert werden. Wenn Sie diese Funktionalität benötigen, müssen Sie Ihre Containerimages mithilfe einer Dockerfile erstellen.
ContainerArchiveOutputPath
Ab .NET 8 können Sie einen Container direkt als Tar.gz-Archiv erstellen. Diese Funktion ist nützlich, wenn Ihr Workflow nicht einfach ist und erfordert, dass Sie beispielsweise ein Scantool über Ihre Bilder ausführen, bevor Sie diese pushen. Nachdem das Archiv erstellt wurde, können Sie es verschieben, scannen oder in eine lokale Docker-Toolkette laden.
Um sie in einem Archiv zu veröffentlichen, fügen Sie die ContainerArchiveOutputPath
Eigenschaft zu Ihrem dotnet publish
-Befehl hinzu, z. B.:
dotnet publish \
-p PublishProfile=DefaultContainer \
-p ContainerArchiveOutputPath=./images/sdk-container-demo.tar.gz
Sie können entweder einen Ordnernamen oder einen Pfad mit einem bestimmten Dateinamen angeben. Wenn Sie den Ordnernamen angeben, lautet der für die Imagearchivdatei generierte Dateiname $(ContainerRepository).tar.gz
. Diese Archive können mehrere Tags enthalten, nur wenn eine einzelne Datei für alle ContainerImageTags
erstellt wird.
Namenskonvention für Containerimages
Containerimages folgen einer bestimmten Namenskonvention. Der Name des Images besteht aus mehreren Teilen, der Registrierung, dem Port (optional), dem Repository und Tag und Familie (optional).
REGISTRY[:PORT]/REPOSITORY[:TAG[-FAMILY]]
Betrachten Sie beispielsweise den vollqualifizierten Imagenamen mcr.microsoft.com/dotnet/runtime:8.0-alpine
:
mcr.microsoft.com
ist die Registrierung (in diesem Fall die Microsoft-Containerregistrierung).dotnet/runtime
ist das Repository (einige betrachten dies jedoch alsuser/repository
).8.0-alpine
ist das Tag und die Familie (die Familie ist ein optionaler Bezeichner, der bei der Zuordnung des Betriebssystempakets hilft).
Einige in den folgenden Abschnitten beschriebene Eigenschaften entsprechen den verwaltenden Bestandteilen des generierten Imagenamens. Beachten Sie die folgende Tabelle, die die Beziehung zwischen dem Imagenamen und den Buildeigenschaften zuordnet:
Bestandteil des Imagenamens | MSBuild-Eigenschaft | Beispielwerte |
---|---|---|
REGISTRY[:PORT] |
ContainerRegistry |
mcr.microsoft.com:443 |
PORT |
ContainerPort |
:443 |
REPOSITORY |
ContainerRepository |
dotnet/runtime |
TAG |
ContainerImageTag |
8.0 |
FAMILY |
ContainerFamily |
-alpine |
Bestandteil des Imagenamens | MSBuild-Eigenschaft | Beispielwerte |
---|---|---|
REGISTRY[:PORT] |
ContainerRegistry |
mcr.microsoft.com:443 |
PORT |
ContainerPort |
:443 |
REPOSITORY |
ContainerImageName |
dotnet/runtime |
TAG |
ContainerImageTag |
8.0 |
In den folgenden Abschnitten werden die verschiedenen Eigenschaften beschrieben, die zum Steuern des generierten Containerimages verwendet werden können.
ContainerBaseImage
Die Eigenschaft „Containerbasisimage“ steuert das Image, das als Basis für Ihr Image dient. Standardmäßig werden die folgenden Werte basierend auf den Eigenschaften Ihres Projekts abgeleitet:
- Wenn Ihr Projekt eigenständig ist, wird das
mcr.microsoft.com/dotnet/runtime-deps
-Image als Basisimage verwendet. - Wenn Ihr Projekt ein ASP.NET Core-Projekt ist, wird das
mcr.microsoft.com/dotnet/aspnet
-Image als Basisimage verwendet. - Andernfalls wird das
mcr.microsoft.com/dotnet/runtime
-Image als Basisimage verwendet.
Das Tag des Images wird als numerische Komponente des ausgewählten TargetFramework
abgeleitet. Beispielsweise führt ein Projekt für net6.0
zum 6.0
-Tag des abgeleiteten Basisimages, und ein net7.0-linux
-Projekt verwendet das 7.0
-Tag usw.
Wenn Sie hier einen Wert festlegen, müssen Sie den vollständig qualifizierten Namen des Images festlegen, das Sie als Basis verwenden möchten, einschließlich aller von Ihnen gewünschten Tags:
<PropertyGroup>
<ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:8.0</ContainerBaseImage>
</PropertyGroup>
<PropertyGroup>
<ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:7.0</ContainerBaseImage>
</PropertyGroup>
ContainerFamily
Ab .NET 8 können Sie die MSBuild-Eigenschaft ContainerFamily
verwenden, um eine andere Familie von Microsoft-Containerimages als Basisimage für Ihre App auszuwählen. Wenn dieser Wert festgelegt ist, wird er am Ende des ausgewählten TFM-spezifischen Tags angefügt, wobei das angegebene Tag geändert wird. Um beispielsweise die Alpine Linux-Varianten der .NET-Basisimages zu verwenden, können Sie ContainerFamily
auf alpine
festlegen:
<PropertyGroup>
<ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>
Die vorherige Projektkonfiguration führt zum endgültigen Tag 8.0-alpine
für eine .NET 8-App.
Dieses Feld ist ein Freiformfeld und kann häufig verwendet werden, um verschiedene Betriebssystemdistributionen, Standardpaketkonfigurationen oder andere Änderungsflavors für ein Basisimage auszuwählen. Dieses Feld wird ignoriert, wenn ContainerBaseImage
festgelegt ist. Weitere Informationen finden Sie unter .NET-Containerimages.
ContainerRuntimeIdentifier
Die Eigenschaft „ContainerRuntimeIdentifier“ steuert das Betriebssystem und die Architektur, die von Ihrem Container verwendet werden, wenn ContainerBaseImage mehr als eine Plattform unterstützt. Beispielsweise unterstützt das Image mcr.microsoft.com/dotnet/runtime
derzeit die Images linux-x64
, linux-arm
, linux-arm64
und win10-x64
hinter demselben Tag. Daher muss dem Tool mitgeteilt werden, welche dieser Versionen Sie verwenden möchten. Standardmäßig wird diese Option auf den RuntimeIdentifier
-Wert festgelegt, den Sie beim Veröffentlichen des Containers ausgewählt haben. Diese Eigenschaft muss selten explizit festgelegt werden. Verwenden Sie stattdessen die Option -r
für den Befehl dotnet publish
. Wenn das von Ihnen ausgewählte Image den von Ihnen ausgewählten RuntimeIdentifier
-Wert nicht unterstützt, wird eine Fehlermeldung mit den RuntimeIdentifiers-Werten angezeigt, die vom Image unterstützt werden.
Sie können die Eigenschaft ContainerBaseImage
immer auf einen vollqualifizierten Imagenamen festlegen, einschließlich des Tags, um diese Eigenschaft überhaupt nicht verwenden zu müssen.
<PropertyGroup>
<ContainerRuntimeIdentifier>linux-arm64</ContainerRuntimeIdentifier>
</PropertyGroup>
Weitere Informationen zu den von .NET unterstützten Runtime-IDs finden Sie im RID-Katalog.
ContainerRegistry
Die Eigenschaft „Containerregistrierung“ steuert die Zielregistrierung und damit den Speicherort, in den das neu erstellte Image gepusht wird. Standardmäßig wird an den lokalen Docker-Daemon gepusht, Sie können aber auch eine Remoteregistrierung angeben. Wenn Sie eine Remoteregistrierung verwenden, die eine Authentifizierung erfordert, authentifizieren Sie sich mithilfe der bekannten docker login
-Mechanismen. Weitere Informationen finden Sie unter Authentifizieren bei Containerregistrierungen. Ein konkretes Beispiel für die Verwendung dieser Eigenschaft finden Sie im folgenden XML-Beispiel:
<PropertyGroup>
<ContainerRegistry>registry.mycorp.com:1234</ContainerRegistry>
</PropertyGroup>
Dieses Tool unterstützt die Veröffentlichung in jeder Registrierung, die die HTTP-API V2 der Docker-Registrierung unterstützt. Dies schließt explizit die folgenden Registrierungen ein (und implizit wahrscheinlich noch viel mehr):
- Azure Container Registry
- Amazon Elastic Container Registry
- Google Artifact Registry
- Docker Hub
- GitHub Packages
- Von GitLab gehostete Containerregistrierung
- Quay.io
Hinweise zur Verwendung dieser Registrierungen finden Sie in den registrierungsspezifischen Hinweisen.
ContainerRepository
Das Containerrepository ist der Name des Images selbst, z. B. dotnet/runtime
oder my-app
. Standardmäßig wird der AssemblyName
des Projekts verwendet.
<PropertyGroup>
<ContainerRepository>my-app</ContainerRepository>
</PropertyGroup>
ContainerImageName
Der Name des Containerimages bestimmt den Namen des Images selbst, z. B dotnet/runtime
oder my-app
. Standardmäßig wird der AssemblyName
des Projekts verwendet.
<PropertyGroup>
<ContainerImageName>my-app</ContainerImageName>
</PropertyGroup>
Hinweis
Ab .NET 8 ist ContainerImageName
zugunsten von ContainerRepository
veraltet.
Imagenamen bestehen aus einem oder mehreren durch Schrägstrich getrennten Segmenten, von denen jedes nur alphanumerische Kleinbuchstaben, Punkte, Unterstriche und Bindestriche enthalten darf und mit einem Buchstaben oder einer Zahl beginnen muss. Alle anderen Zeichen führen dazu, dass ein Fehler ausgelöst wird.
ContainerImageTag(s)
Die Eigenschaft „Containerimagetag“ bestimmt die Tags, die für das Image generiert werden. Um ein einzelnes Tag anzugeben, verwenden Sie ContainerImageTag
. Für mehrere Tags verwenden Sie ContainerImageTags
.
Wichtig
Wenn Sie ContainerImageTags
verwenden, erhalten Sie mehrere Images: eines pro eindeutigem Tag.
Tags dienen häufig zum Verweisen auf verschiedene Versionen einer App. Sie können aber auch auf verschiedene Betriebssystemdistributionen oder sogar unterschiedliche Konfigurationen verweisen.
Ab .NET 8 lautet der Standardwert latest
, wenn kein Tag angegeben wird.
Standardmäßig wird die Version
des Projekts als Tagwert verwendet.
Um die Standardeinstellung zu überschreiben, geben Sie eine der folgenden Optionen an:
<PropertyGroup>
<ContainerImageTag>1.2.3-alpha2</ContainerImageTag>
</PropertyGroup>
Um mehrere Tags anzugeben, geben Sie in der Eigenschaft ContainerImageTags
eine durch Semikolon getrennte Reihe von Tags an, ähnlich wie beim Festlegen mehrerer TargetFrameworks
:
<PropertyGroup>
<ContainerImageTags>1.2.3-alpha2;latest</ContainerImageTags>
</PropertyGroup>
Tags dürfen nur maximal 127 alphanumerische Zeichen, Punkte, Unterstriche und Bindestriche enthalten. Sie müssen mit einem alphanumerischen Zeichen oder Unterstrich beginnen. Jedes andere Format führt dazu, dass ein Fehler ausgelöst wird.
Hinweis
Bei Verwendung von ContainerImageTags
werden die Tags durch ein ;
-Zeichen getrennt. Wenn Sie dotnet publish
über die Befehlszeile aufrufen (wie bei den meisten CI/CD-Umgebungen), müssen Sie die Werte mit einem einzelnen '
umschließen und im Inneren in doppelte Anführungszeichen ("
) einschließen, zum Beispiel: ='"tag-1;tag-2"'
. Betrachten Sie folgenden dotnet publish
-Befehl:
dotnet publish -p ContainerImageTags='"1.2.3-alpha2;latest"'
Das führt dazu, dass zwei Images generiert werden: my-app:1.2.3-alpha2
und my-app:latest
.
Tipp
Wenn Probleme mit der ContainerImageTags
-Eigenschaft auftreten, sollten Sie stattdessen die Umgebungsvariable ContainerImageTags
festlegen:
ContainerImageTags='1.2.3;latest' dotnet publish
ContainerLabel
Die Containerbezeichnung fügt dem Container eine Metadatenbezeichnung hinzu. Bezeichnungen haben zur Laufzeit keine Auswirkungen auf den Container, werden aber häufig zum Speichern von Versions- und Erstellungsmetadaten zur Verwendung durch Sicherheitsscanner und andere Infrastrukturtools genutzt. Sie können eine beliebige Anzahl von Containerbezeichnungen angeben.
Der Knoten ContainerLabel
hat zwei Attribute:
Include
: der Schlüssel der Bezeichnung.Value
: der Wert der Bezeichnung (darf leer sein).
<ItemGroup>
<ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>
Eine Liste der standardmäßig erstellten Bezeichnungen finden Sie unter Standardcontainerbezeichnungen.
Konfigurieren der Containerausführung
Um die Ausführung des Containers zu steuern, können Sie die folgenden MSBuild-Eigenschaften verwenden.
ContainerWorkingDirectory
Der Knoten mit dem Containerarbeitsverzeichnis bestimmt das Arbeitsverzeichnis des Containers, also das Verzeichnis, in dem Befehle ausgeführt werden, wenn kein anderer Befehl ausgeführt wird.
Standardmäßig wird der Verzeichniswert /app
als Arbeitsverzeichnis verwendet.
<PropertyGroup>
<ContainerWorkingDirectory>/bin</ContainerWorkingDirectory>
</PropertyGroup>
ContainerPort
Der Containerport fügt der Liste der bekannten Ports für den Container TCP- oder UDP-Ports hinzu. Dadurch können Containerruntimes wie Docker diese Ports automatisch dem Hostcomputer zuordnen. Dies wird häufig als Dokumentation für den Container verwendet, kann aber auch zum Aktivieren der automatischen Portzuordnung dienen.
Der Knoten ContainerPort
hat zwei Attribute:
Include
: die Portnummer, die verfügbar gemacht werden soll.Type
: standardmäßigtcp
, gültige Werte sindtcp
oderudp
.
<ItemGroup>
<ContainerPort Include="80" Type="tcp" />
</ItemGroup>
Ab .NET 8 wird ContainerPort
basierend auf mehreren bekannten ASP.NET-Umgebungsvariablen abgeleitet, wenn der Wert nicht explizit angegeben wird:
ASPNETCORE_URLS
ASPNETCORE_HTTP_PORTS
ASPNETCORE_HTTPS_PORTS
Wenn diese Umgebungsvariablen vorhanden sind, werden ihre Werte analysiert und in TCP-Portzuordnungen konvertiert. Diese Umgebungsvariablen werden aus Ihrem Basisimage gelesen, sofern vorhanden, oder aus den Umgebungsvariablen, die in Ihrem Projekt definiert sind, über ContainerEnvironmentVariable
-Elemente. Weitere Informationen finden Sie unter ContainerEnvironmentVariable.
ContainerEnvironmentVariable
Der Knoten für die Umgebungsvariablen des Containers ermöglicht Ihnen, dem Container Umgebungsvariablen hinzuzufügen. Umgebungsvariablen sind für die im Container ausgeführte App unmittelbar zugänglich und dienen häufig dazu, das Laufzeitverhalten der ausgeführten App zu ändern.
Der Knoten ContainerEnvironmentVariable
hat zwei Attribute:
Include
: der Name der Umgebungsvariablen.Value
: der Wert der Umgebungsvariablen.
<ItemGroup>
<ContainerEnvironmentVariable Include="LOGGER_VERBOSITY" Value="Trace" />
</ItemGroup>
Weitere Informationen finden Sie unter .NET-Umgebungsvariablen.
Konfigurieren von Containerbefehlen
Standardmäßig starten die Containertools Ihre App entweder mit der generierten AppHost-Binärdatei für Ihre App (wenn Ihre App einen AppHost verwendet) oder durch den Befehl dotnet
und die DLL Ihrer App.
Sie können jedoch steuern, wie Ihre App ausgeführt wird, indem Sie eine Kombination aus ContainerAppCommand
, ContainerAppCommandArgs
, ContainerDefaultArgs
und ContainerAppCommandInstruction
verwenden.
Diese unterschiedlichen Konfigurationspunkte sind vorhanden, da unterschiedliche Basisimages unterschiedliche Kombinationen der Containereigenschaften ENTRYPOINT
und COMMAND
verwenden, und alle davon unterstützt werden sollen. Die Standardwerte sollten von den meisten Apps verwendet werden können. Wenn Sie das App-Startverhalten jedoch anpassen möchten, sollten Sie:
- die auszuführende Binärdatei ermitteln und als
ContainerAppCommand
festlegen - ermitteln, welche Argumente für die Ausführung Ihrer Anwendung erforderlich sind, und diese als
ContainerAppCommandArgs
festlegen - ermitteln, welche Argumente (falls vorhanden) optional sind und von Benutzer*innen überschrieben werden können und diese als
ContainerDefaultArgs
festlegen - Legen Sie
ContainerAppCommandInstruction
aufDefaultArgs
fest.
Weitere Informationen finden Sie in den folgenden Konfigurationselementen.
ContainerAppCommand
Das ContainerAppCommand-Konfigurationselement ist der logische Einstiegspunkt Ihrer App. Für die meisten Apps ist dies der AppHost, die generierte ausführbare Binärdatei für Ihre App. Wenn Ihre App keinen AppHost generiert, lautet dieser Befehl in der Regel dotnet <your project dll>
. Diese Werte werden nach jedem ENTRYPOINT
-Element in Ihrem Basiscontainer oder direkt angewendet, wenn kein ENTRYPOINT
-Element definiert ist.
Die ContainerAppCommand
-Konfiguration weist eine einzelne Include
-Eigenschaft auf, die den Befehl, die Option oder das Argument darstellt, die im Einstiegspunktbefehl verwendet werden sollen:
<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
Dieses ContainerAppCommandArgs-Konfigurationselement stellt alle logisch erforderlichen Argumente für Ihre App dar, die auf ContainerAppCommand
angewendet werden sollen. Standardmäßig werden keine für eine App generiert. Wenn vorhanden, werden die Argumente auf Ihren Container angewendet, wenn er ausgeführt wird.
Die ContainerAppCommandArgs
-Konfiguration verfügt über eine einzelne Include
-Eigenschaft, die die Option oder das Argument darstellt, die auf den Befehl ContainerAppCommand
angewendet werden soll.
<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
Dieses ContainerDefaultArgs-Konfigurationselement stellt alle durch Benutzer*innen überschreibbaren Argumente für Ihre App dar. Das ist eine gute Möglichkeit, Standardwerte anzugeben, die Ihre App benötigt, um leicht gestartet und angepasst werden zu können.
Die ContainerDefaultArgs
-Konfiguration verfügt über eine einzelne Include
-Eigenschaft, die die Option oder das Argument darstellt, die auf den Befehl ContainerAppCommand
angewendet werden soll.
<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
Mit der ContainerAppCommandInstruction-Konfiguration können Sie steuern, wie die ContainerEntrypoint
, ContainerEntrypointArgs
, ContainerAppCommand
, ContainerAppCommandArgs
und ContainerDefaultArgs
kombiniert werden, um den endgültigen Befehl zu bilden, der im Container ausgeführt wird. Hierbei ist maßgeblich, ob ENTRYPOINT
im Basisimage vorhanden ist. Diese Eigenschaft akzeptiert einen von drei Werten: "DefaultArgs"
, "Entrypoint"
oder "None"
.
Entrypoint
:- In diesem Modus wird der Einstiegspunkt durch
ContainerAppCommand
,ContainerAppCommandArgs
undContainerDefaultArgs
definiert.
- In diesem Modus wird der Einstiegspunkt durch
None
:- In diesem Modus wird der Einstiegspunkt durch
ContainerEntrypoint
,ContainerEntrypointArgs
undContainerDefaultArgs
definiert.
- In diesem Modus wird der Einstiegspunkt durch
DefaultArgs
:- Dies ist der komplexeste Modus. Wenn keines der
ContainerEntrypoint[Args]
-Elemente vorhanden ist, werdenContainerAppCommand[Args]
undContainerDefaultArgs
zum Erstellen des Einstiegspunkts und Befehls verwendet. Wenn der Einstiegspunkt für Basisimages aufdotnet
oder/usr/bin/dotnet
hartcodiert ist, wird er übersprungen, sodass Sie die vollständige Kontrolle haben. - Wenn sowohl
ContainerEntrypoint
als auchContainerAppCommand
vorhanden sind, wirdContainerEntrypoint
zum Einstiegspunkt, undContainerAppCommand
wird zum Befehl.
- Dies ist der komplexeste Modus. Wenn keines der
Hinweis
Die Konfigurationselemente ContainerEntrypoint
und ContainerEntrypointArgs
sind ab .NET 8 veraltet.
Wichtig
Dies gilt für fortgeschrittene Benutzer*innen: Die meisten Apps sollten ihren Einstiegspunkt nicht in diesem Maß anpassen müssen. In den Diskussionen zu .NET SDK-Containerbuilds auf GitHub finden Sie weitere Informationen oder können Anwendungsfälle für Ihre Szenarios posten.
ContainerUser
Die Benutzerkonfigurationseigenschaft steuert den Standardbenutzer, der den Container ausführt. Dieser wird häufig verwendet, um den Container als Nicht-Root-Benutzer auszuführen, was eine bewährte Methode für die Sicherheit ist. Es gibt einige Einschränkungen für diese Konfiguration, die Sie beachten sollten:
- Sie kann verschiedene Formate aufweisen (Benutzernamen, Linux-Benutzer-IDs, Gruppenname, Linux-Gruppen-ID,
username:groupname
und andere ID-Varianten). - Es gibt keine Überprüfung, dass der angegebene Benutzer oder die angegebene Gruppe im Image vorhanden ist.
- Das Ändern des Benutzers kann das Verhalten der App beeinflussen, insbesondere in Bezug auf Aspekte wie Dateisystemberechtigungen.
Der Standardwert dieses Felds variiert je nach Projekt-TFM und Zielbetriebssystem:
- Wenn die Zielversion .NET 8 oder höher ist und Sie Microsoft-Runtimeimages verwenden:
- Unter Linux wird der Nicht-Root-Benutzer
app
verwendet (per Benutzer-ID angegeben) - Unter Windows wird der Nicht-Root-Benutzer
ContainerUser
verwendet
- Unter Linux wird der Nicht-Root-Benutzer
- Andernfalls wird standardmäßig kein
ContainerUser
verwendet.
<PropertyGroup>
<ContainerUser>my-existing-app-user</ContainerUser>
</PropertyGroup>
Tipp
Die Umgebungsvariable APP_UID
wird verwendet, um Benutzerinformationen in Ihrem Container festzulegen. Dieser Wert kann aus Umgebungsvariablen stammen, die in Ihrem Basisimage definiert sind (z. B. Microsoft .NET-Images), oder Sie können ihn über die ContainerEnvironmentVariable
-Syntax festlegen.
Sie können jedoch mithilfe von ContainerEntrypoint
und ContainerEntrypointArgs
steuern, wie Ihre App ausgeführt wird.
ContainerEntrypoint
Mithilfe des Containereinstiegspunkts kann der ENTRYPOINT
des Containers angepasst werden. Dabei handelt es sich um die ausführbare Datei, die beim Starten des Containers aufgerufen wird. Bei Builds, die einen App-Host erstellen, ist er standardmäßig auf ContainerEntrypoint
festgelegt. Bei Builds, die keine ausführbare Datei erstellen, wird dotnet path/to/app.dll
als ContainerEntrypoint
verwendet.
Der Knoten ContainerEntrypoint
hat ein einzelnes Attribut:
Include
: der Befehl, die Option oder das Argument zur Verwendung im BefehlContainerEntrypoint
.
Betrachten Sie beispielsweise das folgende Beispiel einer .NET-Projektelementgruppe:
<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
Der Knoten „Args“ des Containereinstiegspunkts bestimmt die Standardargumente, die ContainerEntrypoint
bereitgestellt werden. Er sollte verwendet werden, wenn ContainerEntrypoint
ein Programm ist, das der Benutzer möglicherweise eigenständig verwenden möchte. Standardmäßig werden keine ContainerEntrypointArgs
in Ihrem Auftrag erstellt.
Der Knoten ContainerEntrypointArg
hat ein einzelnes Attribut:
Include
: Die Option oder das Argument, die/das auf den BefehlContainerEntrypoint
angewendet werden soll.
Betrachten Sie die folgende .NET-Projektelementgruppe:
<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>
Standardcontainerbezeichnungen
Bezeichnungen werden häufig verwendet, um konsistente Metadaten für Containerimages bereitzustellen. Dieses Paket enthält einige Standardbezeichnungen, um die generierten Images besser pflegen zu können.
org.opencontainers.image.created
ist auf das ISO 8601-Format der aktuellenDateTime
-Angabe in UTC festgelegt.
Weitere Informationen finden Sie unter Implementieren herkömmlicher Bezeichnungen in einer vorhandenen Bezeichnungsinfrastruktur.
Bereinigen von Ressourcen
In diesem Artikel haben Sie einen .NET-Worker als Containerimage veröffentlicht. Wenn Sie möchten, können Sie diese Ressource löschen. Verwenden Sie den Befehl „docker images
“, um eine Liste der installierten Images anzuzeigen.
docker images
Betrachten Sie die folgende Beispielausgabe:
REPOSITORY TAG IMAGE ID CREATED SIZE
dotnet-worker-image 1.0.0 25aeb97a2e21 12 seconds ago 191MB
Tipp
Imagedateien können groß sein. Normalerweise würden Sie temporäre Container entfernen, die Sie während des Tests und der Entwicklung Ihrer App erstellt haben. In der Regel behalten Sie die Basisimages mit installierter Runtime, wenn Sie planen, andere Images auf Basis dieser Runtime zu erstellen.
Um das Image zu löschen, kopieren Sie die Image-ID und führen den Befehl docker image rm
aus:
docker image rm 25aeb97a2e21