Esercitazione: Compilare e distribuire un'app Web Python con App Azure Container e PostgreSQL
Questo articolo fa parte di una serie di esercitazioni su come inserire e distribuire un'app Web Python in App Azure Container. App contenitore consente di distribuire app in contenitori senza gestire un'infrastruttura complessa.
In questa esercitazione:
- Containerizzare un'app Web di esempio Python (Django o Flask) costruendo un'immagine container nel cloud.
- Distribuire l'immagine del contenitore su Azure Container Apps.
- Definire le variabili di ambiente che consentono all'app contenitore di connettersi a un 'istanza di Database di Azure per PostgreSQL - Server flessibile, in cui l'app di esempio archivia i dati.
Il diagramma seguente illustra le attività di questa esercitazione: creazione e distribuzione di un'immagine del container.
Prerequisiti
Se non hai una sottoscrizione di Azure, crea un account gratuito prima di iniziare.
È possibile eseguire i comandi di Azure CLI in Azure Cloud Shell o su una workstation con Azure CLI installata.
Se si esegue localmente, seguire questa procedura per accedere e installare i moduli necessari per questa esercitazione:
Accedere ad Azure ed eseguire l'autenticazione, se necessario:
az login
Assicurarsi di eseguire la versione più recente dell'interfaccia della riga di comando di Azure:
az upgrade
Installare o aggiornare le estensioni containerapp e rdbms-connect dell'interfaccia della riga di comando di Azure usando il comando az extension add:
az extension add --name containerapp --upgrade az extension add --name rdbms-connect --upgrade
Nota
Per elencare le estensioni installate nel sistema, è possibile usare il comando az extension list. Per esempio:
az extension list --query [].name --output tsv
Ottenere l'app di esempio
Forka e clona il codice di esempio nel tuo ambiente di sviluppo.
Passare al repository GitHub dell'app di esempio (Django o Flask) e selezionare Fork.
Seguire i passaggi per fare il fork del repository nel tuo account GitHub. È anche possibile scaricare il repository del codice direttamente nel computer locale senza creare fork o un account GitHub. Tuttavia, se si usa il metodo del download, non sarà possibile configurare l'integrazione continua e la consegna continua (CI/CD) nel tutorial successivo di questa serie.
Usare il comando git clone per clonare il repository con fork nella cartella python-container :
# Django git clone https://github.com/$USERNAME/msdocs-python-django-azure-container-apps.git python-container # Flask # git clone https://github.com/$USERNAME/msdocs-python-flask-azure-container-apps.git python-container
Cambia la directory:
cd python-container
Creare un'immagine del contenitore dal codice dell'app Web
Dopo aver seguito questa procedura, si avrà un'istanza di Registro Azure Container che contiene un'immagine del contenitore Docker compilata dal codice di esempio.
Creare un gruppo di risorse usando il comando az group create
: az group create \ --name pythoncontainer-rg \ --location <location>
Sostituire <percorso> con uno dei valori
Name
della posizione di Azure dall'output del comandoaz account list-locations -o table
.Creare un registro di container utilizzando il comando az acr create:
az acr create \ --resource-group pythoncontainer-rg \ --name <registry-name> \ --sku Basic \ --admin-enabled
Il nome usato per <nome del Registro di sistema> deve essere univoco in Azure e deve contenere da 5 a 50 caratteri alfanumerici.
Accedere al registro utilizzando il comando az acr login:
az acr login --name <registry-name>
Il comando aggiunge "azurecr.io" al nome per creare il nome completo del Registro di sistema. Se l'accesso ha esito positivo, viene visualizzato il messaggio "Login Succeeded". Se si accede al Registro di sistema da una sottoscrizione diversa da quella in cui è stato creato il Registro di sistema, usare l'opzione
--suffix
.Se l'accesso non riesce, verificare che il daemon Docker sia in esecuzione nel sistema.
Creare l'immagine usando il comando az acr build:
az acr build \ --registry <registry-name> \ --resource-group pythoncontainer-rg \ --image pythoncontainer:latest .
Queste considerazioni si applicano:
Il punto (
.
) alla fine del comando indica il percorso del codice sorgente da compilare. Se non esegui questo comando nella directory radice dell'app di esempio, specifica il percorso del codice.Se si esegue il comando in Azure Cloud Shell, usare
git clone
per eseguire prima il pull del repository nell'ambiente Cloud Shell. Quindi, cambia la directory alla radice del progetto così che il punto (.
) venga interpretato correttamente.Se si esce dall'opzione
-t
(uguale--image
a ), il comando accoda una compilazione di contesto locale senza eseguirne il push nel Registro di sistema. La compilazione senza push può essere utile per verificare che l'immagine venga compilata.
Verificare che l'immagine del container sia stata creata utilizzando il comando az acr repository list:
az acr repository list --name <registry-name>
Nota
I passaggi descritti in questa sezione creano un registro contenitori nel livello di servizio Basic. Questo livello è ottimizzato per i costi, con un set di funzionalità e prestazioni destinati agli scenari di sviluppo ed è adatto ai requisiti di questo tutorial. Negli scenari di produzione è probabile che si usi il livello di servizio Standard o Premium. Questi livelli offrono livelli migliorati di archiviazione e velocità effettiva.
Per altre informazioni, vedere livelli di servizio di Registro Azure Container. Per informazioni sui prezzi, vedere prezzi di Azure Container Registry.
Creare un'istanza del server flessibile PostgreSQL
L'app di esempio (Django o Flask) archivia i dati delle revisioni dei ristoranti in un database PostgreSQL. In questi passaggi viene creato il server che conterrà il database.
Usare il comando az postgres flexible-server create per creare il server PostgreSQL in Azure. Non è insolito che questo comando venga eseguito per alcuni minuti prima che venga completato.
az postgres flexible-server create \ --resource-group pythoncontainer-rg \ --name <postgres-server-name> \ --location <location> \ --admin-user demoadmin \ --admin-password <admin-password> \ --active-directory-auth Enabled \ --tier burstable \ --sku-name standard_b1ms \ --public-access 0.0.0.0
Usare questi valori:
pythoncontainer-rg
: nome del gruppo di risorse usato in questa esercitazione. Se è stato usato un nome diverso, modificare questo valore.<postgres-server-name>: nome del server di database PostgreSQL. Questo nome deve essere univoco in tutto Azure. L'endpoint server è
https://<postgres-server-name>.postgres.database.azure.com
. I caratteri consentiti sonoA
aZ
,0
a9
e trattino (-
).<posizione>: Usare la stessa posizione dell'app Web. <posizione> è uno dei valori
Name
della posizione di Azure dall'output del comandoaz account list-locations -o table
.< > nome utente amministratore: nome utente per l'account amministratore. Non può essere
azure_superuser
,admin
,administrator
,root
,guest
opublic
. Usaredemoadmin
per questa esercitazione.< > : la password dell'utente amministratore. Deve contenere da 8 a 128 caratteri di tre delle categorie seguenti: lettere maiuscole, lettere minuscole, numeri e caratteri non alfanumerici.
Importante
Quando si creano nomi utente o password, non usare il simbolo di dollaro ($). Successivamente, quando si creano variabili di ambiente con questi valori, tale carattere ha un significato speciale all'interno del contenitore Linux usato per eseguire app Python.
--active-directory-auth
: questo valore specifica se l'autenticazione di Microsoft Entra è abilitata nel server PostgreSQL. Impostarlo suEnabled
.--sku-name
: nome del piano tariffario e della configurazione di calcolo; ad esempio,Standard_B1ms
. Per altre informazioni, vedere Piano tariffario di Database di Azure per PostgreSQL. Per elencare i livelli disponibili, usareaz postgres flexible-server list-skus --location <location>
.--public-access
: Usare0.0.0.0
. Consente l'accesso pubblico al server da qualsiasi servizio di Azure, ad esempio App contenitore.
Nota
Se si prevede di utilizzare il server PostgreSQL dalla workstation locale usando degli strumenti, è necessario aggiungere una regola del firewall per l'indirizzo IP della workstation utilizzando il comando az postgres flexible-server firewall-rule create.
Utilizzare il comando az ad signed-in-user show per ottenere l'ID oggetto del tuo account utente. Questo ID viene usato nel comando successivo.
az ad signed-in-user show --query id --output tsv
Usare il comando az postgres flexible-server ad-admin create per aggiungere il tuo account utente come amministratore di Microsoft Entra sul server PostgreSQL.
az postgres flexible-server ad-admin create \ --resource-group pythoncontainer-rg \ --server-name <postgres-server-name> \ --display-name <your-email-address> \ --object-id <your-account-object-id>
Per l'ID oggetto account, utilizza il valore ottenuto nel passaggio precedente.
Nota
I passaggi descritti in questa sezione creano un server PostgreSQL con un singolo vCore e una memoria limitata nel piano tariffario Burstable. Il livello Burstable è un'opzione a basso costo per i carichi di lavoro che non richiedono continuamente l'intera CPU ed è adatto ai requisiti di questo tutorial. Per i carichi di lavoro di produzione, è possibile eseguire l'aggiornamento al piano tariffario Utilizzo generico o Ottimizzato per la memoria. Questi livelli offrono prestazioni più elevate, ma aumentano i costi.
Per ulteriori informazioni, vedere Opzioni di calcolo in Azure Database per PostgreSQL - Server Flessibile. Per informazioni sui prezzi, vedere prezzi di Azure Database per PostgreSQL.
Creare un database nel server
A questo punto, si dispone di un server PostgreSQL. In questa sezione viene creato un database nel server.
Usare il comando az postgres flexible-server db create per creare un database denominato restaurants_reviews:
az postgres flexible-server db create \
--resource-group pythoncontainer-rg \
--server-name <postgres-server-name> \
--database-name restaurants_reviews
Usare questi valori:
-
pythoncontainer-rg
: nome del gruppo di risorse usato in questa esercitazione. Se è stato usato un nome diverso, modificare questo valore. -
<postgres-server-name>
: nome del server PostgreSQL.
È anche possibile usare il comando az postgres flexible-server connect per connettersi al database e quindi usare i comandi psql . Quando si usa psql, è spesso più facile usare Azure Cloud Shell perché la shell include tutte le dipendenze necessarie.
È anche possibile connettersi al server flessibile di Database di Azure per PostgreSQL e creare un database usando psql o un IDE che supporta PostgreSQL, ad esempio Azure Data Studio. Per la procedura con psql, vedere Configurare l'identità gestita nel database PostgreSQL più avanti in questo articolo.
Creare un'identità gestita assegnata dall'utente
Creare un'identità gestita assegnata dall'utente da usare come identità per l'app contenitore quando è in esecuzione in Azure.
Nota
Per creare un'identità gestita assegnata dall'utente, l'account necessita dell'assegnazione di ruolo Contributore di identità gestita.
Usare il comando az identity create per creare un'identità gestita assegnata all'utente.
az identity create --name my-ua-managed-id --resource-group pythoncontainer-rg
Configurare l'identità gestita nel database PostgreSQL
Configurare l'identità gestita come ruolo nel server PostgreSQL e quindi concedere le autorizzazioni necessarie per il database restaurants_reviews. Che si usi Azure CLI o psql, è necessario connettersi al server PostgreSQL di Azure con un utente configurato come amministratore di Microsoft Entra nell'istanza del server. Solo gli account Microsoft Entra configurati come amministratore postgreSQL possono configurare identità gestite e altri ruoli di amministratore Microsoft nel server.
Ottenere un token di accesso per l'account Azure usando il comando az account get-access-token. Il token di accesso viene usato nei passaggi successivi.
az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken
Il token restituito è lungo. Impostare il relativo valore in una variabile di ambiente da usare nei comandi nel passaggio successivo:
MY_ACCESS_TOKEN=<your-access-token>
Aggiungere l'identità gestita assegnata dall'utente come ruolo di database sul server PostgreSQL usando il comando az postgres flexible-server execute:
az postgres flexible-server execute \ --name <postgres-server-name> \ --database-name postgres \ --querytext "select * from pgaadauth_create_principal('"my-ua-managed-id"', false, false);select * from pgaadauth_list_principals(false);" \ --admin-user <your-Azure-account-email> \ --admin-password $MY_ACCESS_TOKEN
Usare questi valori:
Se è stato usato un nome diverso per l'identità gestita, sostituire
my-ua-managed-id
nel comandopgaadauth_create_principal
con il nome dell'identità gestita.Per il valore
--admin-user
, utilizzare l'indirizzo di posta elettronica per l'account Azure.Per il valore
--admin-password
, usare il token di accesso dall'output del comando precedente, senza virgolette.Assicurarsi che il nome del database sia
postgres
.
Nota
Assicurati di eseguire il comando
az postgres flexible-server execute
sulla tua workstation locale e verifica di aver aggiunto una regola del firewall per l'indirizzo IP della tua workstation. È possibile aggiungere una regola utilizzando il comando az postgres flexible-server firewall-rule create. Lo stesso requisito esiste anche per il comando nel passaggio successivo.Concedere le autorizzazioni necessarie all'identità gestita assegnata dall'utente per il database restaurants_reviews usando il seguente comando az postgres flexible-server execute .
az postgres flexible-server execute \ --name <postgres-server-name> \ --database-name restaurants_reviews \ --querytext "GRANT CONNECT ON DATABASE restaurants_reviews TO \"my-ua-managed-id\";GRANT USAGE ON SCHEMA public TO \"my-ua-managed-id\";GRANT CREATE ON SCHEMA public TO \"my-ua-managed-id\";GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"my-ua-managed-id\";ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO \"my-ua-managed-id\";" \ --admin-user <your-Azure-account-email> \ --admin-password $MY_ACCESS_TOKEN
Usare questi valori:
Se è stato usato un nome diverso per l'identità gestita, sostituire tutte le istanze di
my-ua-managed-id
nel comando con il nome dell'identità gestita. Nella stringa di query sono presenti cinque istanze.Per il valore
--admin-user
, usare l'indirizzo di posta elettronica dell'account Azure.Per il valore
--admin-password
, usare il token di accesso dell'output precedente, senza virgolette.Assicurarsi che il nome del database sia
restaurants_reviews
.
Questo comando dell'interfaccia della riga di comando di Azure si connette al database restaurants_reviews nel server ed esegue i comandi SQL seguenti:
GRANT CONNECT ON DATABASE restaurants_reviews TO "my-ua-managed-id"; GRANT USAGE ON SCHEMA public TO "my-ua-managed-id"; GRANT CREATE ON SCHEMA public TO "my-ua-managed-id"; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "my-ua-managed-id"; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "my-ua-managed-id";
Distribuire l'app Web in App contenitore
Le app contenitore vengono distribuite negli ambienti di *Azure Container Apps* , che rappresentano un confine sicuro. Nei passaggi seguenti si creano l'ambiente e un contenitore all'interno dell'ambiente. Si configura quindi il contenitore in modo che il sito Web sia visibile esternamente.
Questi passaggi richiedono l'estensione Azure Container Apps, containerapp.
Creare un ambiente per Container Apps usando il comando az containerapp env create:
az containerapp env create \ --name python-container-env \ --resource-group pythoncontainer-rg \ --location <location>
<posizione> è uno dei valori
Name
della posizione di Azure dall'uscita del comandoaz account list-locations -o table
.Ottenere le credenziali di accesso per l'istanza di Azure Container Registry usando il comando az acr credential show:
az acr credential show -n <registry-name>
Si usa il nome utente e una delle password restituite dall'output del comando quando si crea l'applicazione container nel passaggio 5.
Usare il comando az identity show per ottenere l'ID client e l'ID risorsa dell'identità gestita assegnata dall'utente.
az identity show --name my-ua-managed-id --resource-group pythoncontainer-rg --query "[clientId, id]" --output tsv
Si utilizza il valore dell'ID client (GUID) e l'ID risorsa dell'output del comando, quando si crea l'applicazione contenitore nel passaggio 5. L'ID risorsa ha il formato seguente:
/subscriptions/<subscription-id>/resourcegroups/pythoncontainer-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-ua-managed-id
.Eseguire il comando seguente per generare un valore di chiave privata:
python -c 'import secrets; print(secrets.token_hex())'
Si usa il valore della chiave segreta per impostare una variabile di ambiente quando si crea l'app contenitore nel passaggio 5.
Nota
Il comando illustrato in questo passaggio è relativo a una shell Bash. A seconda dell'ambiente, potrebbe essere necessario richiamare Python usando
python3
. In Windows è necessario racchiudere il comando nel parametro-c
tra virgolette doppie anziché virgolette singole. Potrebbe anche essere necessario richiamare Python usandopy
opy -3
, a seconda dell'ambiente.Creare un'applicazione contenitore nell'ambiente utilizzando il comando az containerapp create.
az containerapp create \ --name python-container-app \ --resource-group pythoncontainer-rg \ --image <registry-name>.azurecr.io/pythoncontainer:latest \ --environment python-container-env \ --ingress external \ --target-port <5000 for Flask or 8000 for Django> \ --registry-server <registry-name>.azurecr.io \ --registry-username <registry-username> \ --registry-password <registry-password> \ --user-assigned <managed-identity-resource-id> \ --query properties.configuration.ingress.fqdn \ --env-vars DBHOST="<postgres-server-name>" \ DBNAME="restaurants_reviews" \ DBUSER="my-ua-managed-id" \ RUNNING_IN_PRODUCTION="1" \ AZURE_CLIENT_ID="<managed-identity-client-id>" \ AZURE_SECRET_KEY="<your-secret-key>"
Assicurarsi di sostituire tutti i valori tra parentesi angolari con i valori usati in questa esercitazione. Tenere presente che il nome dell'app contenitore deve essere univoco nell'intera piattaforma Azure.
Il valore del parametro
--env-vars
è una stringa composta da valori separati da spazi nel formato key="value" con i valori seguenti:DBHOST="\<postgres-server-name>"
DBNAME="restaurants_reviews"
DBUSER="my-ua-managed-id"
RUNNING_IN_PRODUCTION="1"
AZURE_CLIENT_ID="\<managed-identity-client-id>"
AZURE_SECRET_KEY="\<your-secret-key>"
Il valore per
DBUSER
è il nome dell'identità gestita assegnata dall'utente.Il valore per
AZURE_CLIENT_ID
è l'ID client dell'identità gestita assegnata dall'utente. Questo valore è stato ottenuto in un passaggio precedente.Il valore per
AZURE_SECRET_KEY
è il valore della chiave privata generato in un passaggio precedente.Solo per Django, eseguire la migrazione e creare uno schema di database. Nell'app di esempio Flask viene eseguita automaticamente ed è possibile ignorare questo passaggio.
Connettersi utilizzando il comando az containerapp exec:
az containerapp exec \ --name python-container-app \ --resource-group pythoncontainer-rg
Al prompt dei comandi della shell immettere quindi
python manage.py migrate
.Non è necessario eseguire la migrazione per le revisioni del contenitore.
Testare il sito Web.
Il comando
az containerapp create
immesso in precedenza restituisce un URL dell'applicazione che è possibile usare per passare all'app. L'URL termina inazurecontainerapps.io
. Vai all'URL nel browser. In alternativa, è possibile usare il comando az containerapp browse .
Ecco un esempio del sito web di esempio dopo l'aggiunta di un ristorante e due recensioni.
Risolvere i problemi di distribuzione
L'URL dell'applicazione è stata dimenticata per l'accesso al sito Web
Nel portale di Azure:
- Passare alla pagina Panoramica dell'app contenitore e cercare URL dell'applicazione.
In VS Code:
- Passare alla visualizzazione di Azure (Ctrl+Shift+A) ed espandere la sottoscrizione su cui stai lavorando.
- Espandere il nodo Container Apps, espandere l'ambiente gestito, fare clic con il pulsante destro del mouse sul nodo python-container-appe quindi selezionare Sfoglia. VS Code apre il browser con l'URL dell'applicazione.
Nell'interfaccia della riga di comando di Azure:
- Usare il comando
az containerapp show -g pythoncontainer-rg -n python-container-app --query properties.configuration.ingress.fqdn
.
In VS Code l'attività Compila immagine in Azure restituisce un errore
Se viene visualizzato il messaggio "Errore: impossibile scaricare il contesto. "Controllare se l'URL è errato nella finestra di output di VS Code
Se esegui di nuovo l'attività Build Image in Azure, verifica se il registro di una precedente esecuzione esiste. In tal caso, usalo.
Nel portale di Azure viene visualizzato un errore di accesso durante la creazione di un'app contenitore
Un errore di accesso che contiene "Impossibile accedere al nome<del Registro Azure Container>.azurecr.io" si verifica quando le credenziali di amministratore in un'istanza di Registro Azure Container sono disabilitate.
Per controllare lo stato di amministratore nel portale, vai all'istanza di Azure Container Registry, seleziona la risorsa chiavi di accesso e assicurati che l'utente amministratore Admin sia abilitato.
L'immagine del contenitore non viene visualizzata nell'istanza di Registro Azure Container
- Controllare l'output di Azure CLI o di Visual Studio Code e cercare messaggi per confermare il successo.
- Verificare che il nome del Registro di sistema sia stato specificato correttamente nel comando di compilazione con l'interfaccia della riga di comando di Azure o nei prompt delle attività di VS Code.
- Assicurarsi che le credenziali non siano scadute. Ad esempio, in VS Code trovare il Registro di sistema di destinazione nell'estensione Docker e aggiornare. Nell'interfaccia della riga di comando di Azure, eseguire
az login
.
Il sito Web restituisce "Richiesta non valida (400)"
Se viene visualizzato un errore "Richiesta non valida (400)", controllare le variabili di ambiente PostgreSQL passate al contenitore. L'errore 400 indica spesso che il codice Python non è in grado di connettersi all'istanza di PostgreSQL.
Il codice di esempio usato in questa esercitazione verifica l'esistenza della variabile di ambiente del contenitore RUNNING_IN_PRODUCTION
, che può essere impostata su qualsiasi valore ( ad esempio 1
).
Il sito Web restituisce "Non trovato (404)"
- Controllare il valore url applicazione
nella pagina Panoramica del contenitore. Se l'URL dell'applicazione contiene la parola "internal", l'ingresso non è impostato correttamente. - Controllare l'ingresso del contenitore. Ad esempio, nel portale di Azure, vai alla risorsa Ingress del contenitore. Assicurarsi che Ingresso HTTP sia abilitato e che l'opzione Accetta traffico da qualsiasi origine sia selezionata.
Il sito web non si avvia, viene visualizzato un "timeout del flusso" o non viene restituito nulla.
- Controllare i registri:
- Nel portale di Azure passare alla risorsa di gestione delle revisioni dell'app contenitore e controllare Stato del provisioning per il contenitore:
- Se lo stato è provisioning, attendere il completamento del provisioning.
- Se lo stato è Non riuscito, selezionare la revisione e visualizzare i log della console. Scegli l'ordine delle colonne da visualizzare: Time Generated, Stream_se Log_s. Ordinare i log in base ai più recenti e cercare i messaggi di Python
e nella colonna Stream_s del flusso . L'output di Python print
è distdout
messaggi.
- Nell'interfaccia CLI di Azure, utilizzare il comando az containerapp logs show.
- Nel portale di Azure passare alla risorsa di gestione delle revisioni dell'app contenitore e controllare Stato del provisioning per il contenitore:
- Se si usa il framework Django, verificare se le tabelle restaurants_reviews esistono nel database. In caso contrario, usare una console per accedere al contenitore ed eseguire
python manage.py migrate
.