Distribuire un progetto di .NET Aspire in Azure Container Apps usando l'Azure Developer CLI (guida dettagliata)
Il Azure Developer CLI (azd
) è stato esteso per supportare la distribuzione di progetti .NET.NET Aspire. Usa questa guida per seguire il processo di creazione e distribuzione di un progetto .NET Aspire in Azure Container Apps usando il Azure Developer CLI. In questa esercitazione verranno illustrati i concetti seguenti:
- Esplora come funziona l'integrazione
azd
con i progetti .NET.NET Aspire - Fornire e distribuire le risorse su Azure per un progetto .NET Aspire usando
azd
- Generare l'infrastruttura Bicep e altri modelli di file usando
azd
Prerequisiti
Per usare .NET.NET Aspire, è necessario che il codice seguente sia installato in locale:
- .NET 8.0 o .NET 9.0
- Un ambiente di esecuzione dei container conforme a OCI, ad esempio:
- Docker Desktop o Podman. Per altre informazioni, vedere Runtime del contenitore.
- Un ambiente di sviluppo integrato (IDE) o un editor di codice, ad esempio:
- Visual Studio 2022 versione 17.9 o successiva (facoltativo)
-
Visual Studio Code (facoltativo)
- C# Dev Kit: Estensione (facoltativo)
- JetBrains Rider con .NET.NET Aspire plugin (facoltativo)
Per altre informazioni, vedere .NET.NET Aspire configurazione e strumentie .NET.NET Aspire SDK.
Sarà anche necessario che il Azure Developer CLIsia installato localmente. Le opzioni di installazione comuni includono quanto segue:
In che modo funziona l'integrazione di Azure Developer CLI
Il flusso di lavoro azd init
fornisce supporto personalizzato per i progetti .NET.NET Aspire. Il diagramma seguente illustra il funzionamento di questo flusso concettualmente e la modalità di integrazione di azd
e .NET.NET Aspire:
- Quando
azd
è destinato a un progetto .NET.NET Aspire avvia AppHost con un comando speciale (dotnet run --project AppHost.csproj --output-path manifest.json --publisher manifest
), che produce il file manifesto Aspire. - Il file manifesto viene interrogato dalla logica del sottocomando
azd provision
per, per impostazione predefinita, generare file Bicep solo nella memoria. - Dopo aver generato i file Bicep, viene attivata una distribuzione usando le API ARM di Azuredestinate alla sottoscrizione e al gruppo di risorse fornito in precedenza.
- Dopo aver configurato le risorse Azure sottostanti, viene eseguita la logica del sotto-comando
azd deploy
che usa lo stesso manifest file Aspire. - Nell'ambito della distribuzione,
azd
effettua una chiamata adotnet publish
utilizzando il supporto integrato per la pubblicazione di container di .NETper generare immagini di container. - Dopo che
azd
ha creato le immagini del contenitore, le inserisce nel registro ACR, creato durante la fase di provisioning. - Infine, una volta che l'immagine del container si trova nel Registro di Container di Azure,
azd
aggiorna la risorsa utilizzando ARM per iniziare a utilizzare la nuova versione dell'immagine del container.
Nota
azd
consente anche di salvare il Bicep generato in una cartella infra
nel progetto, di cui si può leggere di più nella sezione Generare Bicep dal modello app .NET.NET Aspire alla sezione.
Effettuare il provisioning e distribuire un'app iniziale .NET.NET Aspire
I passaggi descritti in questa sezione illustrano come creare un'app di avvio .NET Aspire e gestire il provisioning e la distribuzione delle risorse dell'app in Azure usando azd
.
Crea la app iniziale .NET.NET Aspire
Creare un nuovo progetto .NET.NET Aspire usando il comando dotnet new
. È anche possibile creare il progetto usando Visual Studio.
dotnet new aspire-starter --use-redis-cache -o AspireSample
cd AspireSample
dotnet run --project AspireSample.AppHost\AspireSample.AppHost.csproj
I comandi precedenti creano un nuovo progetto di .NET.NET Aspire basato sul modello di aspire-starter
che include una dipendenza dalla cache Redis. Esegue il progetto .NET.NET Aspire che verifica che tutto funzioni correttamente.
Inizializzare il modello
Aprire una nuova finestra del terminale e
cd
nella directory del progetto AppHost della soluzione .NET.NET Aspire.Eseguire il comando
azd init
per inizializzare il progetto conazd
, che esamina la struttura di directory locale e determina il tipo di app.azd init
Per altre informazioni sul comando
azd init
, vedere azd init.Selezionare Usa codice nella directory corrente quando ti viene richiesto di scegliere tra due opzioni di inizializzazione dell'app
azd
.? How do you want to initialize your app? [Use arrows to move, type to filter] > Use code in the current directory Select a template
Dopo aver eseguito l'analisi della directory,
azd
chiede di confermare che è stato trovato il progetto di .NET.NET Aspire AppHost corretto. Selezionare l'opzione Conferma e continuare a inizializzare l'app.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
Immettere un nome di ambiente, usato per assegnare un nome alle risorse di cui è stato effettuato il provisioning in Azure e gestire ambienti diversi, ad esempio
dev
eprod
.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
genera un numero di file e li inserisce nella directory di lavoro. Questi file sono:
- azure.yaml: descrive i servizi dell'app, ad esempio il progetto .NET Aspire AppHost, e le mappa alle risorse Azure.
-
.azure/config.json: file di configurazione che informa
azd
qual è l'ambiente attivo corrente. - .azure/aspireazddev/.env: contiene sovrascritture specifiche dell'ambiente.
Il file azure.yaml ha il seguente contenuto:
# 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
Denominazione delle risorse
Quando si creano nuove risorse Azure, è importante rispettare i requisiti di denominazione. Per Azure Container Apps, il nome deve avere una lunghezza di 2-32 caratteri e deve essere costituito da lettere minuscole, numeri e trattini. Il nome deve iniziare con una lettera e terminare con un carattere alfanumerico.
Per altre informazioni, vedere regole di denominazione e restrizioni per le risorse Azure.
Distribuzione iniziale
Per distribuire il progetto .NET Aspire, autenticati in Azure AD per effettuare chiamate alle API di gestione delle risorse Azure.
azd auth login
Il comando precedente avvierà un browser per autenticare la sessione della riga di comando.
Dopo l'autenticazione, eseguire il comando seguente dalla directory del progetto AppHost per provisionare e distribuire l'applicazione.
azd up
Importante
Per eseguire il push delle immagini del container nel Registro Container di Azure (ACR), è necessario avere accesso
Microsoft.Authorization/roleAssignments/write
. A tale scopo, è possibile abilitare un utente amministratore nel Registro di sistema. Aprire il portale di, passare alla risorsa ACR / Impostazioni / Chiavi di accesso e quindi selezionare la casella di controllo utente amministratore . Per ulteriori informazioni, consultare Abilitare l'utente amministratore. Quando richiesto, selezionare la sottoscrizione e il percorso in cui distribuire le risorse. Dopo aver selezionato queste opzioni, verrà distribuito il progetto .NET.NET Aspire.
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.
La riga di output finale del comando
azd
è un collegamento al portale di Azure che mostra tutte le risorse Azure distribuite:
All'interno dell'applicazione vengono distribuiti tre contenitori:
-
webfrontend
: contiene il codice del progetto web nel modello iniziale. -
apiservice
: contiene il codice del progetto del servizio API nel template di avvio. -
cache
: immagine del contenitore Redis per fornire una cache al front-end.
Proprio come nello sviluppo locale, la configurazione delle stringhe di connessione è stata gestita automaticamente. In questo caso, azd
è stato responsabile dell'interpretazione del modello di applicazione e della sua conversione nei passaggi di distribuzione appropriati. Si consideri, ad esempio, la stringa di connessione e le variabili di individuazione del servizio inserite nel contenitore webfrontend
in modo che sappia come connettersi alla cache Redis e apiservice
.
Per altre informazioni su come i progetti .NET.NET Aspire gestiscono le stringhe di connessione e l'individuazione dei servizi, vedere .NET.NET Aspire panoramica dell'orchestrazione.
Distribuire gli aggiornamenti delle applicazioni
Quando viene eseguito il comando azd up
, le risorse sottostanti di Azure vengono fornite e un'immagine del contenitore viene creata e distribuita alle app contenitore che ospitano il progetto .NET.NET Aspire. In genere, una volta avviato lo sviluppo e distribuite le risorse Azure, non sarà necessario effettuare il provisioning delle risorse Azure ogni volta che viene aggiornato il codice. Ciò vale soprattutto per il ciclo interno degli sviluppatori.
Per velocizzare la distribuzione delle modifiche al codice, azd
supporta la distribuzione degli aggiornamenti del codice nell'immagine del contenitore. Questa operazione viene eseguita usando il comando azd deploy
:
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>
Non è necessario distribuire tutti i servizi ogni volta.
azd
comprende il modello di progetto .NET.NET Aspire, è possibile distribuire solo uno dei servizi specificati usando il comando seguente:
azd deploy webfrontend
Per ulteriori informazioni, vedere il riferimento Azure Developer CLI: azd deploy.
Distribuire gli aggiornamenti dell'infrastruttura
Ogni volta che cambia la struttura di dipendenza all'interno di un progetto di .NET.NET Aspire, azd
deve eseguire di nuovo il provisioning delle risorse Azure sottostanti. Il comando azd provision
viene usato per applicare queste modifiche all'infrastruttura.
Per visualizzare questa operazione in azione, aggiornare il file Program.cs nel progetto AppHost nel modo seguente:
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();
Salvare il file ed eseguire il comando seguente:
azd provision
Il comando azd provision
aggiorna l'infrastruttura creando un'app contenitore per ospitare il database Postgres. Il comando azd provision
non ha aggiornato le stringhe di connessione per il contenitore apiservice
. Per fare in modo che le stringhe di connessione vengano aggiornate in modo che puntino al database di Postgres appena sottoposto a provisioning, è necessario richiamare nuovamente il comando azd deploy
. In caso di dubbio, usare azd up
sia per effettuare il provisioning che per la distribuzione.
Pulire le risorse
Ricorda di pulire le risorse Azure che hai creato durante questa procedura dettagliata. Poiché `azd conosce il gruppo di risorse in cui ha creato le risorse, può essere utilizzato per disattivare l'ambiente usando il comando seguente:
azd down
L'esecuzione del comando precedente può richiedere del tempo, ma quando è stato completato il gruppo di risorse e tutte le relative risorse devono essere eliminate.
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.
Generare Bicep dal modello di progetto .NET.NET Aspire
Anche se i team di sviluppo sono liberi di usare azd up
(o azd provision
e azd deploy
) comandi per le distribuzioni sia a scopo di sviluppo che di produzione, alcuni team possono scegliere di generare file Bicep che possono esaminare e gestire come parte del controllo della versione (in questo modo questi file Bicep possono essere referenziati come parte di una distribuzione più complessa Azure).
azd
include la possibilità di fornire il Bicep utilizzato per il provisioning tramite il seguente comando:
azd config set alpha.infraSynth on
azd infra synth
Dopo aver eseguito questo comando nell'esempio di modello iniziale usato in questa guida, i file seguenti vengono creati nella directory del progetto AppHost:
- infra/main.bicep: Indica il punto di ingresso principale per la distribuzione.
- infra/main.parameters.json: utilizzato come parametri per il main Bicep (mappa alle variabili di ambiente definite nella cartella .azure).
- infra/resources.bicep: definisce le risorse di Azure necessarie per supportare il modello di progetto .NET Aspire.
-
AspireSample.Web/manifests/containerApp.tmpl.yaml: definizione dell'applicazione contenitore per
webfrontend
. -
AspireSample.ApiService/manifests/containerApp.tmpl.yaml: Definizione dell'applicazione container per
apiservice
.
Il file infra\resources.bicep non contiene alcuna definizione delle app contenitore stesse (ad eccezione delle app contenitore che sono dipendenze, ad esempio Redis e Postgres):
@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
Per altre informazioni sull'uso di Bicep per automatizzare le distribuzioni in Azure, vedi Che cos'è Bicep?
La definizione delle app contenitore dai progetti di servizio .NET è contenuta rispettivamente nei file containerApp/tmpl.ya ml nella directory manifests
di ogni progetto. Di seguito è riportato un esempio del progetto webfrontend
:
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
Dopo aver eseguito il comando azd infra synth
, quando azd provision
e azd deploy
vengono chiamati usano i file generati da Bicep e supportati.
Importante
Se azd infra synth
viene chiamato di nuovo, sostituisce tutti i file modificati con quelli appena generati e richiede conferma prima di farlo.
Ambienti isolati per il debug
Poiché azd
semplifica il provisioning di nuovi ambienti, è possibile che ogni membro del team abbia un ambiente ospitato nel cloud isolato per il debug del codice in un'impostazione che corrisponde strettamente alla produzione. Quando si esegue questa operazione, ogni membro del team deve creare il proprio ambiente usando il comando seguente:
azd env new
Verrà richiesta di nuovo all'utente le informazioni sulla sottoscrizione e sul gruppo di risorse e le successive azd up
, azd provision
e azd deploy
chiamate useranno questo nuovo ambiente per impostazione predefinita. L'opzione --environment
può essere applicata a questi comandi per passare da un ambiente all'altro.
Pulire le risorse
Esegui il seguente comando CLI di Azure per eliminare il gruppo di risorse quando le risorse Azure non sono più necessarie. L'eliminazione del gruppo di risorse comporta anche l'eliminazione delle risorse contenute all'interno di essa.
az group delete --name <your-resource-group-name>
Per altre informazioni, vedere Eseguire la pulizia delle risorse in Azure.