Bereitstellen eines .NET Aspire Projekts zum Azure Container Apps mithilfe des Azure Developer CLI (ausführliche Anleitung)
Die Azure Developer CLI (azd
) wurde erweitert, um die Bereitstellung von .NET-.NET Aspire-Projekten zu unterstützen. In diesem Leitfaden werden Sie schrittweise durch den Prozess zum Erstellen und Bereitstellen eines .NET Aspire Projekts auf Azure Container Apps mithilfe von Azure Developer CLIgeführt. In diesem Lernprogramm lernen Sie die folgenden Konzepte kennen:
- Erfahren Sie, wie
azd
Integration mit .NET.NET Aspire Projekten funktioniert - Bereitstellung und Einsatz von Ressourcen auf Azure für ein .NET Aspire-Projekt mit Hilfe von
azd
- Generieren von Bicep-Infrastruktur und anderen Vorlagendateien mithilfe von
azd
Voraussetzungen
Um mit .NET.NET Aspirezu arbeiten, benötigen Sie folgendes lokal installiert:
- .NET 8.0 oder .NET 9,0
- Eine OCI-kompatible Containerlaufzeit, z. B.:
- Docker Desktop oder Podman. Weitere Informationen finden Sie unter container runtime.
- Eine integrierte Entwicklerumgebung (Integrated Developer Environment, IDE) oder ein Code-Editor, z. B.:
- Visual Studio 2022 Version 17.9 oder höher (optional)
-
Visual Studio Code (optional)
- C# Dev Kit: Erweiterung (Optional)
- JetBrains Rider mit .NET.NET Aspire Plug-in (Optional)
Weitere Informationen finden Sie unter .NET.NET Aspire Einrichtung und Werkzeugerstellungund .NET.NET Aspire SDK.
Außerdem müssen Sie die Azure Developer CLIlokal installiert haben. Zu den allgemeinen Installationsoptionen gehören die folgenden:
Funktionsweise der Azure Developer CLI-Integration
Der azd init
-Workflow bietet maßgeschneiderte Unterstützung für .NET-.NET Aspire-Projekte. Das folgende Diagramm veranschaulicht, wie dieser Fluss konzeptionell funktioniert und wie azd
und .NET.NET Aspire integriert werden:
- Wenn
azd
auf ein .NET.NET Aspire Projekt ausgerichtet ist, wird der AppHost mit einem speziellen Befehl (dotnet run --project AppHost.csproj --output-path manifest.json --publisher manifest
) gestartet, der die AspireManifestdateierzeugt. - Die Manifestdatei wird von der Unterbefehlslogik
azd provision
abgefragt, um Bicep-Dateien standardmäßig nur im Arbeitsspeicher zu generieren. - Nach dem Generieren der Bicep-Dateien wird eine Bereitstellung mithilfe der ARM-APIs von Azurefür das zuvor angegebene Abonnement und die Ressourcengruppe ausgelöst.
- Nachdem die zugrunde liegenden Azure Ressourcen konfiguriert wurden, wird die
azd deploy
Unterbefehlslogik ausgeführt, die dieselbe Aspire Manifestdatei verwendet. - Im Rahmen der Bereitstellung ruft
azd
dotnet publish
auf, mithilfe der integrierten Containerveröffentlichungs-Unterstützung von .NET, um Containerabbilder zu generieren. - Sobald
azd
die Containerimages erstellt hat, überträgt es sie an die ACR-Registry, die während der Bereitstellungsphase erstellt wurde. - Nachdem sich das Containerimage in ACR befindet, aktualisiert
azd
die Ressource mit ARM, um mit der Verwendung der neuen Version des Containerimages zu beginnen.
Anmerkung
azd
ermöglicht es Ihnen auch, den generierten Bicep in einem infra
Ordner in Ihrem Projekt auszugeben, über den Sie im Abschnitt Generieren von Bicep aus .NET.NET Aspire App-Modell mehr lesen können.
Bereitstellen und Implementieren einer .NET.NET Aspire Starter-App
Die Schritte in diesem Abschnitt veranschaulichen, wie Sie eine .NET Aspire-Start-App erstellen und die App-Ressourcen mithilfe von Azurebereitstellen und in azd
einsetzen.
Erstellen Sie die .NET.NET Aspire Start-App
Erstellen Sie mithilfe des Befehls dotnet new
ein neues .NET.NET Aspire Projekt. Sie können das Projekt auch mit Visual Studioerstellen.
dotnet new aspire-starter --use-redis-cache -o AspireSample
cd AspireSample
dotnet run --project AspireSample.AppHost\AspireSample.AppHost.csproj
Die vorherigen Befehle erstellen ein neues .NET.NET Aspire Projekt basierend auf der aspire-starter
Vorlage, die eine Abhängigkeit vom Redis Cache enthält. Es führt das .NET.NET Aspire Projekt aus, das überprüft, ob alles ordnungsgemäß funktioniert.
Vorlage initialisieren
Öffnen Sie ein neues Terminalfenster, und
cd
Sie in das AppHost- Projektverzeichnis Ihrer .NET.NET Aspire Lösung ein.Führen Sie den befehl
azd init
aus, um Ihr Projekt mitazd
zu initialisieren, wodurch die lokale Verzeichnisstruktur überprüft und der App-Typ bestimmt wird.azd init
Weitere Informationen zum Befehl
azd init
finden Sie unter azd init.Wählen Sie Code im aktuellen Verzeichnis verwenden aus, wenn
azd
Sie mit zwei App-Initialisierungsoptionen auffordert.? How do you want to initialize your app? [Use arrows to move, type to filter] > Use code in the current directory Select a template
Nach dem Scannen des Verzeichnisses werden Sie von
azd
aufgefordert, zu bestätigen, dass es das richtige .NET.NET AspireAppHost- Projekt gefunden hat. Wählen Sie die Option "Bestätigen und mit der Initialisierung meiner App fortfahren."Detected services: .NET (Aspire) Detected in: D:\source\repos\AspireSample\AspireSample.AppHost\AspireSample.AppHost.csproj azd will generate the files necessary to host your app on Azure using Azure Container Apps. ? Select an option [Use arrows to move, type to filter] > Confirm and continue initializing my app Cancel and exit
Geben Sie einen Umgebungsnamen ein, der verwendet wird, um bereitgestellte Ressourcen in Azure zu benennen und verschiedene Umgebungen wie
dev
undprod
zu verwalten.Generating files to run your app on Azure: (✓) Done: Generating ./azure.yaml (✓) Done: Generating ./next-steps.md SUCCESS: Your app is ready for the cloud! You can provision and deploy your app to Azure by running the azd up command in this directory. For more information on configuring your app, see ./next-steps.md
azd
generiert eine Reihe von Dateien und platziert sie in das Arbeitsverzeichnis. Diese Dateien sind:
- azure.yaml: Beschreibt die Dienste der App, wie z. B. das .NET Aspire AppHost-Projekt, und ordnet sie Azure Ressourcen zu.
-
.azure/config.json: Konfigurationsdatei, die
azd
darüber informiert, welche die aktuelle Umgebung ist. - .azure/aspireazddev/.env: Enthält umgebungsspezifische Außerkraftsetzungen.
Die azureYAML- Datei hat den folgenden Inhalt:
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json
name: AspireSample
services:
app:
language: dotnet
project: .\AspireSample.AppHost\AspireSample.AppHost.csproj
host: containerapp
Ressourcen-Namensgebung
Wenn Sie neue Azure Ressourcen erstellen, ist es wichtig, die Benennungsanforderungen zu erfüllen. Bei Azure Container Appsmuss der Name 2 bis 32 Zeichen lang sein und aus Kleinbuchstaben, Zahlen und Bindestrichen bestehen. Der Name muss mit einem Buchstaben beginnen und mit einem alphanumerischen Zeichen enden.
Weitere Informationen finden Sie unter Benennungsregeln und Einschränkungen für Azure Ressourcen.
Erste Bereitstellung
Um das .NET Aspire Projekt bereitzustellen, authentifizieren Sie sich bei Azure AD, um die Azure Ressourcenverwaltungs-APIs aufzurufen.
azd auth login
Der vorherige Befehl startet einen Browser, um die Befehlszeilensitzung zu authentifizieren.
Führen Sie nach der Authentifizierung den folgenden Befehl im AppHost--Projektverzeichnis aus, um die Anwendung bereitzustellen und zu implementieren.
azd up
Wichtig
Um Container-Images in die Azure Containerregistrierung (Container Registry, ACR) zu übertragen, müssen Sie über
Microsoft.Authorization/roleAssignments/write
Zugriff verfügen. Dies kann erreicht werden, indem ein Administratorbenutzer im Registry aktiviert wird. Öffnen Sie das Azure Portal, navigieren Sie zu den ACR-Ressourcen/Einstellungen/Zugriffstasten, und aktivieren Sie dann das Kontrollkästchen Administratorbenutzer. Weitere Informationen finden Sie unter Administratorbenutzer aktivieren.Wenn Sie dazu aufgefordert werden, wählen Sie das Abonnement und den Speicherort aus, in dem die Ressourcen bereitgestellt werden sollen. Sobald diese Optionen ausgewählt sind, wird das .NET.NET Aspire Projekt implementiert.
By default, a service can only be reached from inside the Azure Container Apps environment it is running in. Selecting a service here will also allow it to be reached from the Internet. ? Select which services to expose to the Internet webfrontend ? Select an Azure Subscription to use: 1. <YOUR SUBSCRIPTION> ? Select an Azure location to use: 1. <YOUR LOCATION> Packaging services (azd package) Provisioning Azure resources (azd provision) Provisioning Azure resources can take some time. Subscription: <YOUR SUBSCRIPTION> Location: <YOUR LOCATION> You can view detailed progress in the Azure Portal: <LINK TO DEPLOYMENT> (✓) Done: Resource group: <YOUR RESOURCE GROUP> (✓) Done: Container Registry: <ID> (✓) Done: Log Analytics workspace: <ID> (✓) Done: Container Apps Environment: <ID> SUCCESS: Your application was provisioned in Azure in 1 minute 13 seconds. You can view the resources created under the resource group <YOUR RESOURCE GROUP> in Azure Portal: <LINK TO RESOURCE GROUP OVERVIEW> Deploying services (azd deploy) (✓) Done: Deploying service apiservice - Endpoint: <YOUR UNIQUE apiservice APP>.azurecontainerapps.io/ (✓) Done: Deploying service webfrontend - Endpoint: <YOUR UNIQUE webfrontend APP>.azurecontainerapps.io/ Aspire Dashboard: <LINK TO DEPLOYED .NET ASPIRE DASHBOARD> SUCCESS: Your up workflow to provision and deploy to Azure completed in 3 minutes 50 seconds.
Die letzte Zeile der Ausgabe des Befehls
azd
ist ein Link zum Azure-Portal, das alle bereitgestellten Azure-Ressourcen zeigt:
In dieser Anwendung werden drei Container bereitgestellt:
-
webfrontend
: Enthält Code aus dem Webprojekt in der Startvorlage. -
apiservice
: Enthält Code aus dem API-Dienstprojekt in der Startvorlage. -
cache
: Ein Redis Containerimage, um einen Cache für das Front-End bereitzustellen.
Genau wie bei der lokalen Entwicklung wurde die Konfiguration von Verbindungszeichenfolgen automatisch behandelt. In diesem Fall war azd
für die Interpretation des Anwendungsmodells und die Übersetzung in die entsprechenden Bereitstellungsschritte verantwortlich. Betrachten Sie beispielsweise die Verbindungszeichenfolgen und Variablen zur Dienstentdeckung, die in den Container webfrontend
eingefügt werden, damit er weiß, wie er sich mit dem Redis-Cache und apiservice
verbinden kann.
Weitere Informationen dazu, wie .NET.NET Aspire Projekte Verbindungszeichenfolgen und Dienstermittlung behandeln, finden Sie in .NET.NET Aspire Übersicht über die Orchestrierung.
Bereitstellen von Anwendungsupdates
Wenn der befehl azd up
ausgeführt wird, werden die zugrunde liegenden Azure Ressourcen bereitgestellt und ein Containerimage erstellt und für die Container-Apps bereitgestellt, die das .NET.NET Aspire Projekt hosten. In der Regel ist es, sobald die Entwicklung läuft und Azure Ressourcen bereitgestellt werden, nicht notwendig, Azure Ressourcen bei jeder Code-Aktualisierung bereitzustellen – besonders trifft das für den sogenannten "Developer Inner Loop" zu.
Um die Bereitstellung von Codeänderungen zu beschleunigen, unterstützt azd
die Bereitstellung von Codeupdates im Container-Image. Dazu wird der Befehl azd deploy
verwendet:
azd deploy
Deploying services (azd deploy)
(✓) Done: Deploying service apiservice
- Endpoint: <YOUR UNIQUE apiservice APP>.azurecontainerapps.io/
(✓) Done: Deploying service webfrontend
- Endpoint: <YOUR UNIQUE webfrontend APP>.azurecontainerapps.io/
Aspire Dashboard: <LINK TO DEPLOYED .NET ASPIRE DASHBOARD>
Es ist nicht erforderlich, alle Dienste jedes Mal bereitzustellen.
azd
versteht das .NET.NET Aspire Projektmodell, und daher ist es möglich, nur einen der Dienste bereitzustellen, die mit dem folgenden Befehl angegeben sind:
azd deploy webfrontend
Weitere Informationen finden Sie unter Azure Developer CLI Referenz: azd deploy.
Bereitstellung von Infrastruktur-Updates
Wenn sich die Abhängigkeitsstruktur innerhalb eines .NET.NET Aspire Projekts ändert, muss azd
die zugrunde liegenden Azure Ressourcen erneut bereitstellen. Der Befehl azd provision
wird verwendet, um diese Änderungen auf die Infrastruktur anzuwenden.
Um dies in Aktion anzuzeigen, aktualisieren Sie die Program.cs Datei im AppHost-Projekt wie folgt:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedis("cache");
// Add the locations database.
var locationsdb = builder.AddPostgres("db").AddDatabase("locations");
// Add the locations database reference to the API service.
var apiservice = builder.AddProject<Projects.AspireSample_ApiService>("apiservice")
.WithReference(locationsdb);
builder.AddProject<Projects.AspireSample_Web>("webfrontend")
.WithReference(cache)
.WithReference(apiservice);
builder.Build().Run();
Speichern Sie die Datei, und stellen Sie den folgenden Befehl aus:
azd provision
Der befehl azd provision
aktualisiert die Infrastruktur, indem eine Container-App zum Hosten der Postgres-Datenbank erstellt wird. Der Befehl azd provision
hat die Verbindungszeichenfolgen für den container apiservice
nicht aktualisiert. Damit Verbindungszeichenfolgen so aktualisiert werden, dass sie auf die neu bereitgestellte Postgres Datenbank verweisen, muss der Befehl azd deploy
erneut aufgerufen werden. Verwenden Sie im Zweifelsfall azd up
sowohl für die Bereitstellung als auch für den Einsatz.
Bereinigen von Ressourcen
Denken Sie daran, die Azure Ressourcen aufzuräumen, die Sie während dieser Anleitung erstellt haben. Da "azd" die Ressourcengruppe kennt, in der es die Ressourcen erstellt hat, kann es verwendet werden, um die Umgebung mit dem folgenden Befehl herunterzufahren:
azd down
Der vorherige Befehl kann einige Zeit in Anspruch nehmen, aber nach Abschluss sollten die Ressourcengruppe und alle zugehörigen Ressourcen gelöscht sein.
Deleting all resources and deployed code on Azure (azd down)
Local application code is not deleted when running 'azd down'.
Resource group(s) to be deleted:
• <YOUR RESOURCE GROUP>: <LINK TO RESOURCE GROUP OVERVIEW>
? Total resources to delete: 7, are you sure you want to continue? Yes
Deleting your resources can take some time.
(✓) Done: Deleting resource group: <YOUR RESOURCE GROUP>
SUCCESS: Your application was removed from Azure in 9 minutes 59 seconds.
Bicep aus dem Projektmodell .NET.NET Aspire generieren
Obwohl Entwicklungsteams die Befehle azd up
(oder azd provision
und azd deploy
) sowohl für Entwicklungs- als auch für Produktionszwecke frei verwenden können, entscheiden sich einige Teams möglicherweise dazu, Bicep-Dateien zu generieren, die sie im Rahmen der Versionsverwaltung überprüfen und verwalten können. Dies ermöglicht außerdem, dass auf diese Bicep-Dateien als Teil einer größeren, komplexeren Azure-Bereitstellung verwiesen wird.
azd
umfasst die Möglichkeit, die bei der Bereitstellung verwendete Bicep-Datei über den folgenden Befehl auszugeben:
azd config set alpha.infraSynth on
azd infra synth
Nachdem dieser Befehl im in diesem Leitfaden verwendeten Beispiel für die Startvorlage ausgeführt wurde, werden die folgenden Dateien im AppHost- Projektverzeichnis erstellt:
- infra/main.bicep: Stellt den Haupteinstiegspunkt für die Bereitstellung dar.
- infra/main.parameters.json: Wird als Parameter für die Haupt-Bicep verwendet (ordnet Umgebungsvariablen zu, die in definiert sind.azure Ordner).
- infra/resources.bicep: Definiert die Azure Ressourcen, die erforderlich sind, um das .NET Aspire Projektmodell zu unterstützen.
-
AspireSample.Web/manifests/containerApp.tmpl.yaml: Die Container-App-Definition für
webfrontend
. -
AspireSample.ApiService/manifests/containerApp.tmpl.yaml: Die Container-App-Definition für
apiservice
.
Die infra\resources.bicep Datei enthält keine Definition der Container-Apps selbst (mit Ausnahme von Container-Apps, die Abhängigkeiten wie Redis und Postgressind):
@description('The location used for all deployed resources')
param location string = resourceGroup().location
@description('Tags that will be applied to all resources')
param tags object = {}
var resourceToken = uniqueString(resourceGroup().id)
resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: 'mi-${resourceToken}'
location: location
tags: tags
}
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-07-01' = {
name: replace('acr-${resourceToken}', '-', '')
location: location
sku: {
name: 'Basic'
}
tags: tags
}
resource caeMiRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(containerRegistry.id, managedIdentity.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d'))
scope: containerRegistry
properties: {
principalId: managedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
}
}
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
name: 'law-${resourceToken}'
location: location
properties: {
sku: {
name: 'PerGB2018'
}
}
tags: tags
}
resource containerAppEnvironment 'Microsoft.App/managedEnvironments@2023-05-01' = {
name: 'cae-${resourceToken}'
location: location
properties: {
appLogsConfiguration: {
destination: 'log-analytics'
logAnalyticsConfiguration: {
customerId: logAnalyticsWorkspace.properties.customerId
sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
}
}
}
tags: tags
}
resource cache 'Microsoft.App/containerApps@2023-05-02-preview' = {
name: 'cache'
location: location
properties: {
environmentId: containerAppEnvironment.id
configuration: {
service: {
type: 'redis'
}
}
template: {
containers: [
{
image: 'redis'
name: 'redis'
}
]
}
}
tags: union(tags, {'aspire-resource-name': 'cache'})
}
resource locations 'Microsoft.App/containerApps@2023-05-02-preview' = {
name: 'locations'
location: location
properties: {
environmentId: containerAppEnvironment.id
configuration: {
service: {
type: 'postgres'
}
}
template: {
containers: [
{
image: 'postgres'
name: 'postgres'
}
]
}
}
tags: union(tags, {'aspire-resource-name': 'locations'})
}
output MANAGED_IDENTITY_CLIENT_ID string = managedIdentity.properties.clientId
output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.properties.loginServer
output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = managedIdentity.id
output AZURE_CONTAINER_APPS_ENVIRONMENT_ID string = containerAppEnvironment.id
output AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN string = containerAppEnvironment.properties.defaultDomain
Weitere Informationen darüber, wie Sie mit Bicep Bereitstellungen für Azure automatisieren können, finden Sie unter Was ist Bicep?
Die Definition der Container-Apps aus den Dienstprojekten .NET befindet sich in den Dateien containerApp/tmpl.yaml im Verzeichnis manifests
innerhalb jedes Projekts. Hier ist ein Beispiel aus dem webfrontend
Projekt:
location: {{ .Env.AZURE_LOCATION }}
identity:
type: UserAssigned
userAssignedIdentities:
? "{{ .Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID }}"
: {}
properties:
environmentId: {{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_ID }}
configuration:
activeRevisionsMode: single
ingress:
external: true
targetPort: 8080
transport: http
allowInsecure: false
registries:
- server: {{ .Env.AZURE_CONTAINER_REGISTRY_ENDPOINT }}
identity: {{ .Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID }}
template:
containers:
- image: {{ .Env.SERVICE_WEBFRONTEND_IMAGE_NAME }}
name: webfrontend
env:
- name: AZURE_CLIENT_ID
value: {{ .Env.MANAGED_IDENTITY_CLIENT_ID }}
- name: ConnectionStrings__cache
value: {{ connectionString "cache" }}
- name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES
value: "true"
- name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES
value: "true"
- name: services__apiservice__0
value: http://apiservice.internal.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}
- name: services__apiservice__1
value: https://apiservice.internal.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}
tags:
azd-service-name: webfrontend
aspire-resource-name: webfrontend
Nach dem Ausführen des befehls azd infra synth
, wenn azd provision
und azd deploy
aufgerufen werden, verwenden sie Bicep und unterstützende generierte Dateien.
Wichtig
Wenn azd infra synth
erneut aufgerufen wird, werden alle geänderten Dateien durch frisch generierte Dateien ersetzt und Sie vor diesem Vorgang zur Bestätigung aufgefordert.
Isolierte Umgebungen für das Debuggen
Da azd
die Bereitstellung neuer Umgebungen vereinfacht, ist es für jedes Teammitglied möglich, eine isolierte cloudgehostete Umgebung für das Debuggen von Code in einer Einstellung zu haben, die eng mit der Produktion übereinstimmt. Dabei sollten alle Teammitglieder ihre eigene Umgebung mit dem folgenden Befehl erstellen:
azd env new
Dies wird den Benutzer erneut nach Informationen zu Abonnement und Ressourcengruppe fragen, und anschließende Aufrufe von azd up
, azd provision
und azd deploy
werden standardmäßig diese neue Umgebung verwenden. Der --environment
Switch kann auf diese Befehle angewendet werden, um zwischen Umgebungen zu wechseln.
Bereinigen von Ressourcen
Führen Sie den folgenden Azure CLI-Befehl aus, um die Ressourcengruppe zu löschen, wenn Sie die von Ihnen erstellten Azure Ressourcen nicht mehr benötigen. Durch das Löschen der Ressourcengruppe werden auch die darin enthaltenen Ressourcen gelöscht.
az group delete --name <your-resource-group-name>
Weitere Informationen finden Sie unter Ressourcen bereinigen in Azure.