Esercitazione: Connettersi al database PostgreSQL da un'applicazione contenitore Java Quarkus senza segreti tramite un'identità gestita

App contenitore di Azure offre un'identità gestita per l'app, una soluzione chiavi in mano per proteggere l'accesso a Database di Azure per PostgreSQL e ad altri servizi di Azure. Le identità gestite nelle App contenitore rendono l'app più sicura eliminando i segreti dall'app, ad esempio le credenziali nelle variabili di ambiente.

Questa esercitazione illustra il processo di creazione, configurazione, distribuzione e ridimensionamento di app contenitore Java in Azure. Alla fine di questa esercitazione si avrà un'applicazione Quarkus che archivia i dati in un database PostgreSQL con un'identità gestita in esecuzione in App contenitore.

Contenuto dell'esercitazione:

  • Configurare un'app Quarkus per l'autenticazione usando Microsoft Entra ID con un database PostgreSQL.
  • Creare un registro Azure Container ed eseguire il push di un'immagine dell'app Java in esso.
  • Creare un'app contenitore in Azure.
  • Creare un database PostgreSQL in Azure.
  • Connettersi al database PostgreSQL con identità gestita tramite la funzionalità Connettore servizio.

Se non si ha una sottoscrizione di Azure, creare un account Azure gratuito prima di iniziare.

1. Prerequisiti

2. Creare un registro contenitori

Creare un gruppo di risorse con il comando az group create. Un gruppo di risorse di Azure è un contenitore logico in cui le risorse di Azure vengono distribuite e gestite.

L'esempio seguente crea un gruppo di risorse nell'area di Azure denominata myResourceGroup nell'area di Azure Stati Uniti orientali.

RESOURCE_GROUP="myResourceGroup"
LOCATION="eastus"

az group create --name $RESOURCE_GROUP --location $LOCATION

Creare un'istanza del Registro Azure Container usando il comando az acr create e recuperarne il server di accesso usando il comando az acr show . Il nome del registro deve essere univoco in Azure e contenere da 5 a 50 caratteri alfanumerici. Tutte le lettere devono essere specificate in minuscolo. Il seguente esempio usa mycontainerregistry007. Aggiornarlo a un valore univoco.

REGISTRY_NAME=mycontainerregistry007
az acr create \
    --resource-group $RESOURCE_GROUP \
    --name $REGISTRY_NAME \
    --sku Basic

REGISTRY_SERVER=$(az acr show \
    --name $REGISTRY_NAME \
    --query 'loginServer' \
    --output tsv | tr -d '\r')

3. Clonare l'app di esempio e preparare l'immagine del contenitore

In questa esercitazione viene usata un'app elenco Frutta di esempio con un'interfaccia utente Web che chiama un'API REST Quarkus supportata da Database di Azure per PostgreSQL. Il codice per l'app è disponibile in GitHub. Per altre informazioni sulla scrittura di app Java con Quarkus e PostgreSQL, vedere la Guida a Quarkus Hibernate ORM con Panache e la Guida a Quarkus Datasource.

Eseguire i comandi seguenti nel terminale per clonare il repository di esempio e configurare l'ambiente dell'app di esempio.

git clone https://github.com/quarkusio/quarkus-quickstarts
cd quarkus-quickstarts/hibernate-orm-panache-quickstart

Modificare il progetto

  1. Aggiungere le dipendenze necessarie al file BOM del progetto.

    <dependency>
       <groupId>com.azure</groupId>
       <artifactId>azure-identity-extensions</artifactId>
       <version>1.1.20</version>
    </dependency>
    
  2. Configurare le proprietà dell'app Quarkus.

    La configurazione di Quarkus si trova nel file src/main/resources/application.properties. Aprire questo file nell'editor e osservare diverse proprietà predefinite. Le proprietà precedute da %prod vengono usate solo quando l'applicazione viene compilata e distribuita, ad esempio quando viene distribuita nel servizio app di Azure. Quando l'applicazione viene eseguita in locale, le proprietà %prod vengono ignorate. Analogamente, le proprietà %dev vengono usate nella modalità live coding/sviluppo di Quarkus e le proprietà %test vengono usate durante i test continui.

    Eliminare il contenuto esistente in application.properties e sostituire con quanto segue per configurare il database per le modalità di sviluppo, test e produzione:

    quarkus.hibernate-orm.database.generation=drop-and-create
    quarkus.datasource.db-kind=postgresql
    quarkus.datasource.jdbc.max-size=8
    quarkus.datasource.jdbc.min-size=2
    quarkus.hibernate-orm.log.sql=true
    quarkus.hibernate-orm.sql-load-script=import.sql
    quarkus.datasource.jdbc.acquisition-timeout = 10
    
    %dev.quarkus.datasource.username=${CURRENT_USERNAME}
    %dev.quarkus.datasource.jdbc.url=jdbc:postgresql://${AZURE_POSTGRESQL_HOST}:${AZURE_POSTGRESQL_PORT}/${AZURE_POSTGRESQL_DATABASE}?\
    authenticationPluginClassName=com.azure.identity.extensions.jdbc.postgresql.AzurePostgresqlAuthenticationPlugin\
    &sslmode=require
    
    %prod.quarkus.datasource.username=${AZURE_POSTGRESQL_USERNAME}
    %prod.quarkus.datasource.jdbc.url=jdbc:postgresql://${AZURE_POSTGRESQL_HOST}:${AZURE_POSTGRESQL_PORT}/${AZURE_POSTGRESQL_DATABASE}?\
    authenticationPluginClassName=com.azure.identity.extensions.jdbc.postgresql.AzurePostgresqlAuthenticationPlugin\
    &sslmode=require
    
    %dev.quarkus.class-loading.parent-first-artifacts=com.azure:azure-core::jar,\
    com.azure:azure-core-http-netty::jar,\
    io.projectreactor.netty:reactor-netty-core::jar,\
    io.projectreactor.netty:reactor-netty-http::jar,\
    io.netty:netty-resolver-dns::jar,\
    io.netty:netty-codec::jar,\
    io.netty:netty-codec-http::jar,\
    io.netty:netty-codec-http2::jar,\
    io.netty:netty-handler::jar,\
    io.netty:netty-resolver::jar,\
    io.netty:netty-common::jar,\
    io.netty:netty-transport::jar,\
    io.netty:netty-buffer::jar,\
    com.azure:azure-identity::jar,\
    com.azure:azure-identity-extensions::jar,\
    com.fasterxml.jackson.core:jackson-core::jar,\
    com.fasterxml.jackson.core:jackson-annotations::jar,\
    com.fasterxml.jackson.core:jackson-databind::jar,\
    com.fasterxml.jackson.dataformat:jackson-dataformat-xml::jar,\
    com.fasterxml.jackson.datatype:jackson-datatype-jsr310::jar,\
    org.reactivestreams:reactive-streams::jar,\
    io.projectreactor:reactor-core::jar,\
    com.microsoft.azure:msal4j::jar,\
    com.microsoft.azure:msal4j-persistence-extension::jar,\
    org.codehaus.woodstox:stax2-api::jar,\
    com.fasterxml.woodstox:woodstox-core::jar,\
    com.nimbusds:oauth2-oidc-sdk::jar,\
    com.nimbusds:content-type::jar,\
    com.nimbusds:nimbus-jose-jwt::jar,\
    net.minidev:json-smart::jar,\
    net.minidev:accessors-smart::jar,\
    io.netty:netty-transport-native-unix-common::jar,\
    net.java.dev.jna:jna::jar
    

Compilare ed eseguire il push di un'immagine Docker nel registro contenitori

  1. Compilare l'immagine del contenitore.

    Eseguire il comando seguente per compilare l'immagine dell'app Quarkus. È necessario contrassegnarlo con il nome completo del server di accesso del Registro di sistema.

    CONTAINER_IMAGE=${REGISTRY_SERVER}/quarkus-postgres-passwordless-app:v1
    
    mvn quarkus:add-extension -Dextensions="container-image-jib"
    mvn clean package -Dquarkus.container-image.build=true -Dquarkus.container-image.image=${CONTAINER_IMAGE}
    
  2. Accedere al Registro di sistema.

    Prima di eseguire il push delle immagini del contenitore, è necessario accedere al registro. A tale scopo, usare il comando [az acr login][az-acr-login].

    az acr login --name $REGISTRY_NAME
    

    Il comando restituisce un messaggio Login Succeeded al termine dell'esecuzione.

  3. Eseguire il push dell'immagine nel registro.

    Usare [docker push][docker-push] per eseguire il push dell'immagine nell'istanza del Registro di sistema. Questo esempio crea il repository quarkus-postgres-passwordless-app che contiene l'immagine quarkus-postgres-passwordless-app:v1.

    docker push $CONTAINER_IMAGE
    

4. Creare un'app contenitore in Azure

  1. Creare un'istanza di App contenitore eseguendo il comando seguente. Assicurarsi di sostituire il valore delle variabili di ambiente con il nome e la posizione effettivi da usare.

    CONTAINERAPPS_ENVIRONMENT="my-environment"
    
    az containerapp env create \
        --resource-group $RESOURCE_GROUP \
        --name $CONTAINERAPPS_ENVIRONMENT \
        --location $LOCATION
    
  2. Creare un'app contenitore con l'immagine dell'app eseguendo il comando seguente:

    APP_NAME=my-container-app
    az containerapp create \
        --resource-group $RESOURCE_GROUP \
        --name $APP_NAME \
        --image $CONTAINER_IMAGE \
        --environment $CONTAINERAPPS_ENVIRONMENT \
        --registry-server $REGISTRY_SERVER \
        --registry-identity system \
        --ingress 'external' \
        --target-port 8080 \
        --min-replicas 1
    

    Nota

    Le opzioni --registry-username e --registry-password sono ancora supportate, ma non sono consigliate perché l'uso del sistema di identità è più sicuro.

5. Creare e connettere un database PostgreSQL con connettività di identità

Creare quindi un database PostgreSQL e configurare l'app contenitore per connettersi a un database PostgreSQL con un'identità gestita assegnata dal sistema. L'app Quarkus si connetterà a questo database e archivierà i propri dati durante l'esecuzione, rendendo persistente lo stato dell'applicazione indipendentemente dalla posizione in cui viene eseguita.

  1. Creare il servizio del database.

    DB_SERVER_NAME='msdocs-quarkus-postgres-webapp-db'
    
    az postgres flexible-server create \
        --resource-group $RESOURCE_GROUP \
        --name $DB_SERVER_NAME \
        --location $LOCATION \
        --public-access None \
        --sku-name Standard_B1ms \
        --tier Burstable \
        --active-directory-auth Enabled
    

    Nota

    Le opzioni --admin-user e --admin-password sono ancora supportate, ma non sono consigliate perché l'uso del sistema di identità è più sicuro.

    I parametri seguenti vengono usati nel comando dell'interfaccia della riga di comando di Azure precedente:

    • gruppo di risorse → Usare lo stesso nome del gruppo di risorse in cui è stata creata l'app Web, msdocs-quarkus-postgres-webapp-rgad esempio .
    • nome → il nome del server di database PostgreSQL. Questo nome deve essere univoco in tutti gli ambienti di Azure (l'endpoint server diventa https://<name>.postgres.database.azure.com). I caratteri consentiti sono A-Z, 0-9 e -. Un criterio valido consiste nell'usare una combinazione del nome della società e di un identificatore del server. (msdocs-quarkus-postgres-webapp-db)
    • posizione → Usare la stessa posizione usata per l'app Web. Se non funziona, passare a una posizione diversa.
    • public-accessNone che imposta il server in modalità di accesso pubblico senza regole del firewall. Le regole verranno create in un passaggio successivo.
    • sku-name → Il nome del piano tariffario e della configurazione di calcolo, Standard_B1msad esempio . Per altre informazioni, vedere Piano tariffario di Database di Azure per PostgreSQL.
    • livello → il livello di calcolo del server. Per altre informazioni, vedere Piano tariffario di Database di Azure per PostgreSQL.
    • active-directory-authEnabled per abilitare l'autenticazione di Microsoft Entra.
  2. Creare un database denominato fruits all'interno del servizio PostgreSQL con questo comando:

    DB_NAME=fruits
    az postgres flexible-server db create \
        --resource-group $RESOURCE_GROUP \
        --server-name $DB_SERVER_NAME \
        --database-name $DB_NAME
    
  3. Installare l'estensione senza password Connettore di servizi per l'interfaccia della riga di comando di Azure:

    az extension add --name serviceconnector-passwordless --upgrade --allow-preview true
    
  4. Connettere il database all'app contenitore con un'identità gestita assegnata dal sistema usando il comando di connessione.

    az containerapp connection create postgres-flexible \
        --resource-group $RESOURCE_GROUP \
        --name $APP_NAME \
        --target-resource-group $RESOURCE_GROUP \
        --server $DB_SERVER_NAME \
        --database $DB_NAME \
        --system-identity \
        --container $APP_NAME
    

6. Esaminare le modifiche

È possibile trovare l'URL dell'applicazione (FQDN) usando il comando seguente:

echo https://$(az containerapp show \
    --name $APP_NAME \
    --resource-group $RESOURCE_GROUP \
    --query properties.configuration.ingress.fqdn \
    --output tsv)

Quando nella nuova pagina Web viene visualizzato l'elenco di frutti, l'app si connette al database con l'identità gestita. Dovrebbe ora essere possibile modificare l'elenco di frutta come in precedenza.

Pulire le risorse

Nei passaggi precedenti sono state create risorse di Azure in un gruppo di risorse. Se si ritiene che queste risorse non saranno necessarie in futuro, eliminare il gruppo di risorse eseguendo questo comando in Cloud Shell:

az group delete --name myResourceGroup

L'esecuzione del comando può richiedere un minuto.

Passaggi successivi

Altre informazioni sull'esecuzione di app Java in Azure sono disponibili nella guida per sviluppatori.