Share via


Implementación de una aplicación Java con Quarkus en una instancia de Azure Container Apps

En este artículo se muestra cómo implementar rápidamente Red Hat Quarkus en Microsoft Azure Container Apps con una sencilla aplicación CRUD. La aplicación es una "lista de tareas pendientes" con un front-end de JavaScript y un punto de conexión REST. Azure Database for PostgreSQL proporciona la capa de persistencia para la aplicación. En el artículo se muestra cómo probar la aplicación localmente e implementarla en Container Apps.

Requisitos previos

  • Si no tiene una suscripción a Azure, cree una cuenta gratuita antes de empezar.
  • Azure Cloud Shell tiene todos estos requisitos previos preinstalados. Para obtener más información, consulte Inicio rápido para Azure Cloud Shell.
  • Si ejecuta los comandos de esta guía localmente (en lugar de usar Azure Cloud Shell), complete los pasos siguientes:
    • Prepare una máquina local con un sistema operativo similar a Unix instalado (por ejemplo, Ubuntu, macOS o Subsistema de Windows para Linux).
    • Instale una implementación de Java SE versión 17 o posterior (por ejemplo, microsoft build of OpenJDK).
    • Instale Maven 3.5.0 o una versión superior.
    • Instale Docker o Podman para el sistema operativo.
    • Instale jq.
    • Instale cURL.
    • Instale la CLI de Quarkus 3.4.1 o posterior.
  • CLI de Azure para entornos similares a Unix. En este artículo solo se requiere la variante bash de la CLI de Azure.
    • Instale la CLI de Azure e inicie sesión de forma interactiva con el comando az login para iniciar sesión en Azure antes de usar DefaultAzureCredential en el código.
      az login
      
    • Este artículo requiere al menos la versión 2.31.0 de la CLI de Azure. Si usa Azure Cloud Shell, ya está instalada la versión más reciente.

Crear el proyecto de la aplicación

Use el siguiente comando para clonar el proyecto de Java de ejemplo para este artículo. El ejemplo se encuentra en GitHub.

git clone https://github.com/Azure-Samples/quarkus-azure
cd quarkus-azure
git checkout 2023-09-13
cd aca-quarkus

Si ve un mensaje acerca de estar en estado HEAD desasociado, este mensaje es seguro de omitir. Dado que este artículo no requiere ninguna confirmación, el estado HEAD desasociado es adecuado.

Prueba local de la aplicación Quarkus

Los pasos de esta sección muestran cómo ejecutar la aplicación localmente.

Quarkus admite el aprovisionamiento automático de servicios no configurados en modo de desarrollo y prueba. Quarkus hace referencia a esta funcionalidad como servicios de desarrollo. Supongamos que incluye una característica de Quarkus, como conectarse a un servicio de base de datos. Quiere probar la aplicación, pero aún no ha configurado completamente la conexión a una base de datos real. Quarkus inicia automáticamente una versión de código auxiliar del servicio pertinente y conecta la aplicación a ella. Para obtener más información, consulte Información general de Dev Services en la documentación de Quarkus.

Asegúrese de que el entorno de contenedor, Docker o Podman, se está ejecutando y use el siguiente comando para especificar el modo de desarrollo de Quarkus:

quarkus dev

En lugar de quarkus dev, puede lograr lo mismo con Maven mediante mvn quarkus:dev.

Es posible que se le pregunte si desea enviar telemetría del uso del modo de desarrollo de Quarkus. Si es así, responda como quiera.

El modo de desarrollo de Quarkus habilita la recarga en vivo con la compilación en segundo plano. Si modifica algún aspecto del código fuente de la aplicación y actualiza el explorador, puede ver los cambios. Si hay algún problema con la compilación o la implementación, una página de error le informará. El modo de desarrollo de Quarkus escucha un depurador en el puerto 5005. Si desea esperar a que el depurador se adjunte antes de ejecutarse, pase -Dsuspend en la línea de comandos. Si no quiere el depurador en absoluto, puede usar -Ddebug=false.

La salida debería tener un aspecto similar al ejemplo siguiente:

__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
INFO  [io.quarkus] (Quarkus Main Thread) quarkus-todo-demo-app-aca 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.2.0.Final) started in 14.826s. Listening on: http://localhost:8080
INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-validator, jdbc-postgresql, narayana-jta, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx]

--
Tests paused
Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>

Presione w en el terminal donde se está ejecutando el modo de desarrollo de Quarkus. La tecla w abre el explorador web predeterminado para mostrar la aplicación Todo. También puede acceder a la GUI de la aplicación directamente en http://localhost:8080.

Screenshot of the Todo sample app.

Intente seleccionar algunos elementos de tareas pendientes en la lista de tareas pendientes. La interfaz de usuario indica la selección con un estilo de texto tachado. También puede agregar un nuevo elemento de tareas pendientes a la lista de tareas pendientes escribiendo Comprobar aplicaciones de tareas pendientes y presionando ENTRAR, como se muestra en la captura de pantalla siguiente:

Screenshot of the Todo sample app with new items added.

Acceda a la API de RESTful (/api) para obtener todos los elementos de tareas pendientes que se almacenan en la base de datos de PostgreSQL local:

curl --verbose http://localhost:8080/api | jq .

La salida debería tener un aspecto similar al ejemplo siguiente:

* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /api HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 664
< Content-Type: application/json;charset=UTF-8
<
{ [664 bytes data]
100   664  100   664    0     0  13278      0 --:--:-- --:--:-- --:--:-- 15441
* Connection #0 to host localhost left intact
[
  {
    "id": 1,
    "title": "Introduction to Quarkus Todo App",
    "completed": false,
    "order": 0,
    "url": null
  },
  {
    "id": 2,
    "title": "Quarkus on Azure App Service",
    "completed": false,
    "order": 1,
    "url": "https://learn.microsoft.com/en-us/azure/developer/java/eclipse-microprofile/deploy-microprofile-quarkus-java-app-with-maven-plugin"
  },
  {
    "id": 3,
    "title": "Quarkus on Azure Container Apps",
    "completed": false,
    "order": 2,
    "url": "https://learn.microsoft.com/en-us/training/modules/deploy-java-quarkus-azure-container-app-postgres/"
  },
  {
    "id": 4,
    "title": "Quarkus on Azure Functions",
    "completed": false,
    "order": 3,
    "url": "https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-first-quarkus"
  },
  {
    "id": 5,
    "title": "Verify Todo apps",
    "completed": false,
    "order": 5,
    "url": null
  }
]

Presione q para salir del modo de desarrollo de Quarkus.

Creación de los recursos de Azure para ejecutar la aplicación Quarkus

Los pasos de esta sección muestran cómo crear los siguientes recursos de Azure para ejecutar la aplicación de ejemplo Quarkus:

  • Microsoft Azure Database for PostgreSQL
  • Microsoft Azure Container Registry
  • Aplicaciones de contenedor

Algunos de estos recursos deben tener nombres únicos dentro del ámbito de la suscripción de Azure. Para garantizar esta unicidad, puede usar el patrón de iniciales, secuencia, fecha y sufijo. Para aplicar este patrón, asigne un nombre a los recursos enumerando las iniciales, algún número de secuencia, la fecha de hoy y algún tipo de sufijo específico del recurso, por ejemplo, rg para "grupo de recursos". Use los siguientes comandos para definir algunas variables de entorno para usarlas más adelante:

export UNIQUE_VALUE=<your unique value, such as ejb091223>
export RESOURCE_GROUP_NAME=${UNIQUE_VALUE}rg
export LOCATION=<your desired Azure region for deploying your resources. For example, eastus>
export REGISTRY_NAME=${UNIQUE_VALUE}reg
export DB_SERVER_NAME=${UNIQUE_VALUE}db
export DB_PASSWORD=Secret123456
export ACA_ENV=${UNIQUE_VALUE}env
export ACA_NAME=${UNIQUE_VALUE}aca

Creación de una instancia de Azure Database for PostgreSQL

Azure Database for PostgreSQL es un servicio administrado que usa para ejecutar, administrar y escalar bases de datos de PostgreSQL de alta disponibilidad en la nube. Esta sección le dirige a un inicio rápido independiente que muestra cómo crear un servidor único de Azure Database for PostgreSQL y conectarse a él. Sin embargo, cuando siga los pasos del inicio rápido, debe usar la configuración de la tabla siguiente para personalizar la implementación de la base de datos para la aplicación Quarkus de ejemplo. Reemplace las variables de entorno por sus valores reales al rellenar los campos en Azure Portal.

Configuración valor Descripción
Grupo de recursos ${RESOURCE_GROUP_NAME} Seleccione Crear nuevo. La implementación crea este nuevo grupo de recursos.
Nombre del servidor ${DB_SERVER_NAME} Este valor forma parte del nombre de host del servidor de bases de datos.
Ubicación ${LOCATION} Seleccione una ubicación en la lista desplegable. Tome nota de la ubicación. Debe usar esta misma ubicación para otros recursos de Azure que cree.
Nombre de usuario administrador quarkus El código de ejemplo supone este valor.
Contraseña ${DB_PASSWORD} La contraseña debe tener al menos 8 caracteres y, como máximo, 128 caracteres. La contraseña debe contener caracteres de tres de las siguientes categorías: letras en mayúsculas del alfabeto inglés, letras en minúscula del alfabeto inglés, números (0-9) y caracteres no alfanuméricos (!, $, #, %, etc.). La contraseña no puede contener todo o parte del nombre de inicio de sesión. Parte de un nombre de inicio de sesión se define como tres o más caracteres alfanuméricos consecutivos.

Teniendo en cuenta estas sustituciones de valor, siga los pasos descritos en Inicio rápido: Creación de un servidor de Azure Database for PostgreSQL mediante el Azure Portal hasta la sección "Configurar una regla de firewall". A continuación, en la sección "Configurar una regla de firewall", asegúrese de seleccionar para Permitir el acceso a los servicios de Azure y, a continuación, seleccione Guardar. Si no lo hace, la aplicación Quarkus no puede acceder a la base de datos y simplemente no se inicia nunca.

Después de completar los pasos del inicio rápido a través de la sección "Configuración de una regla de firewall", incluido el paso para permitir el acceso a los servicios de Azure, vuelva a este artículo.

Creación de una base de datos todo en Azure Database for PostgreSQL

El servidor de PostgreSQL que creó anteriormente está vacío. No tiene ninguna base de datos que pueda usar con la aplicación de Quarkus. Cree una nueva base de datos llamada todo con el comando siguiente:

az postgres db create \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name todo \
    --server-name ${DB_SERVER_NAME}

Debe usar todo como nombre de la base de datos porque el código de ejemplo asume ese nombre para la base de datos.

Si el comando se ejecuta correctamente, la salida es similar al ejemplo siguiente:

{
  "charset": "UTF8",
  "collation": "English_United States.1252",
  "id": "/subscriptions/REDACTED/resourceGroups/ejb091223rg/providers/Microsoft.DBforPostgreSQL/servers/ejb091223db/databases/todo",
  "name": "todo",
  "resourceGroup": "ejb091223rg",
  "type": "Microsoft.DBforPostgreSQL/servers/databases"
}

Crear una instancia de Microsoft Azure Container Registry

Dado que Quarkus es una tecnología nativa en la nube, tiene compatibilidad integrada para crear contenedores que se ejecutan en Container Apps. Container Apps depende completamente de tener un registro de contenedor desde el que encuentra las imágenes de contenedor que se van a ejecutar. Container Apps tiene compatibilidad integrada con Azure Container Registry.

Use el comando az acr create para crear la instancia de Container Registry. En el ejemplo siguiente se crea una instancia de Container Registry denominada con el valor de la variable ${REGISTRY_NAME}de entorno :

az acr create \
    --resource-group $RESOURCE_GROUP_NAME \
    --location ${LOCATION} \
    --name $REGISTRY_NAME \
    --sku Basic \
    --admin-enabled

Tras un breve período de tiempo, debería ver una salida JSON que contiene las siguientes líneas:

  "provisioningState": "Succeeded",
  "publicNetworkAccess": "Enabled",
  "resourceGroup": "<YOUR_RESOURCE_GROUP>",

Conectar docker a la instancia de Container Registry

Inicie sesión en la instancia de Container Registry. El inicio de sesión le permite insertar una imagen. Use los comandos siguientes para comprobar la conexión:

export LOGIN_SERVER=$(az acr show \
    --name $REGISTRY_NAME \
    --query 'loginServer' \
    --output tsv)
echo $LOGIN_SERVER
export USER_NAME=$(az acr credential show \
    --name $REGISTRY_NAME \
    --query 'username' \
    --output tsv)
echo $USER_NAME
export PASSWORD=$(az acr credential show \
    --name $REGISTRY_NAME \
    --query 'passwords[0].value' \
    --output tsv)
echo $PASSWORD
docker login $LOGIN_SERVER -u $USER_NAME -p $PASSWORD

Si usa Podman en lugar de Docker, realice los cambios necesarios en el comando.

Si ha iniciado sesión correctamente en la instancia de Container Registry, debería ver Login Succeeded al final de la salida del comando.

Creación de un entorno

Un entorno de Azure Container Apps crea un límite seguro alrededor de un grupo de aplicaciones de contenedor. Las aplicaciones de contenedor implementadas en el mismo entorno se implementan en la misma red virtual y escriben registros en la misma área de trabajo de Log Analytics. Use el comando az containerapp env create para crear un entorno, como se muestra en el ejemplo siguiente:

az containerapp env create \
    --resource-group $RESOURCE_GROUP_NAME \
    --location $LOCATION \
    --name $ACA_ENV

Si se le pide que instale una extensión, responda a Y.

Personalización de la configuración nativa de la nube

Como tecnología nativa en la nube, Quarkus ofrece la capacidad de generar automáticamente imágenes de contenedor. Para obtener más información, consulte Imágenes de contenedor. A continuación, los desarrolladores pueden implementar la imagen de aplicación en una plataforma en contenedores de destino, por ejemplo, Azure Container Apps.

Para generar la imagen de contenedor, use el siguiente comando para agregar la extensión en el container-image-jib terminal local:

quarkus ext add container-image-jib

Quarkus modifica el POM para asegurarse de que la extensión se incluye entre .<dependencies> Si se le pide que instale algo llamado JBang, responda y permita que se instale.

La salida debería tener un aspecto similar al ejemplo siguiente:

[SUCCESS] ✅  Extension io.quarkus:quarkus-container-image-jib has been installed

Para comprobar que se agregan las extensiones, puede ejecutar git diff y examinar la salida.

Como tecnología nativa en la nube, Quarkus admite la noción de perfiles de configuración. Quarkus tiene los tres perfiles integrados siguientes:

  • dev - Activado cuando está en modo de desarrollo.
  • test - Activado al ejecutar pruebas.
  • prod - Perfil predeterminado cuando no se ejecuta en modo de desarrollo o prueba.

Quarkus admite cualquier número de perfiles con nombre, según sea necesario.

Los pasos restantes de esta sección le dirigen a quitar la marca de comentario y personalizar los valores en el archivo src/main/resources/application.properties. Asegúrese de que todas las líneas que comienzan por # %prod. estén sin la marca de comentario, eliminando los caracteres # iniciales.

El prefijo %prod. indica que estas propiedades están activas al ejecutarse en el perfil prod. Para obtener más información sobre los perfiles de configuración, consulte la documentación de Quarkus.

Personalización de la configuración de la base de datos

Agregue las siguientes variables de configuración de base de datos. Reemplace los valores de <DB_SERVER_NAME_VALUE> y <DB_PASSWORD_VALUE> por los valores reales de las ${DB_SERVER_NAME} variables de entorno y ${DB_PASSWORD} , respectivamente.

# Database configurations
%prod.quarkus.datasource.db-kind=postgresql
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://<DB_SERVER_NAME_VALUE>.postgres.database.azure.com:5432/todo
%prod.quarkus.datasource.jdbc.driver=org.postgresql.Driver
%prod.quarkus.datasource.username=quarkus@<DB_SERVER_NAME_VALUE>
%prod.quarkus.datasource.password=<DB_PASSWORD_VALUE>
%prod.quarkus.hibernate-orm.database.generation=create
%prod.quarkus.hibernate-orm.sql-load-script=no-file

Por lo general, no se espera que los datos almacenados en la base de datos se quiten y se vuelvan a rellenar con los datos de ejemplo en un entorno de producción. Por eso puede ver que se especifica create el esquema de para quarkus.hibernate-orm.database.generation para que la aplicación solo cree el esquema cuando no exista en el inicio inicial. Además, la base de datos no se rellena previamente con ningún dato de ejemplo porque hibernate-orm.sql-load-script se especifica como no-file. Esta configuración es diferente de cuando ejecutó la aplicación localmente en modo de desarrollo anteriormente. Los valores predeterminados en modo de desarrollo para quarkus.hibernate-orm.database.generation y son drop-and-create y hibernate-orm.sql-load-scriptimport.sql respectivamente, lo que significa que la aplicación siempre quita y vuelve a crear el esquema de la base de datos y carga los datos definidos en import.sql. El archivo import.sql es una comodidad de Quarkus. Si el archivo src/main/resources/import.sql existe en el archivo jar de Quarkus y el valor de la hibernate-orm.sql-load-script propiedad es import.sql, las instrucciones DML de SQL de este archivo se ejecutan en tiempo de inicio para la aplicación.

Personalización de la configuración de la imagen de contenedor

Como tecnología nativa en la nube, Quarkus admite la generación de imágenes de contenedor OCI compatibles con Docker y Podman. Agregue las siguientes variables de imagen de contenedor. Reemplace los valores de <LOGIN_SERVER_VALUE> y <USER_NAME_VALUE> por los valores de los valores reales de las variables de entorno ${LOGIN_SERVER} y ${USER_NAME}, respectivamente.

# Container Image Build
%prod.quarkus.container-image.build=true
%prod.quarkus.container-image.registry=<LOGIN_SERVER_VALUE>
%prod.quarkus.container-image.group=<USER_NAME_VALUE>
%prod.quarkus.container-image.name=todo-quarkus-aca
%prod.quarkus.container-image.tag=1.0

Compilación de la imagen de contenedor e inserción en Container Registry

Ahora, use el siguiente comando para compilar la propia aplicación. Este comando usa la extensión Jib para compilar la imagen de contenedor.

quarkus build --no-tests

La salida debe terminar con BUILD SUCCESS.

Puede comprobar si también se genera la imagen de contenedor mediante la docker línea de comandos o podman (CLI). El resultado es similar al ejemplo siguiente:

docker images | grep todo-quarkus-aca
<LOGIN_SERVER_VALUE>/<USER_NAME_VALUE>/todo-quarkus-aca   1.0       0804dfd834fd   2 minutes ago   402MB

Inserte las imágenes de contenedor en Container Registry mediante el comando siguiente:

export TODO_QUARKUS_TAG=$(docker images | grep todo-quarkus-aca | head -n1 | cut -d " " -f1):1.0
echo ${TODO_QUARKUS_TAG}
docker push ${TODO_QUARKUS_TAG}

La salida debería tener un aspecto similar al ejemplo siguiente:

The push refers to repository [<LOGIN_SERVER_VALUE>/<USER_NAME_VALUE>/todo-quarkus-aca]
188a550fce3d: Pushed
4e3afea591e2: Pushed
1db0eba807a6: Pushed
c72d9ccda0b2: Pushed
d7819b8a2d18: Pushed
d0e5cba6b262: Pushed
e0bac91f0f10: Pushed
1.0: digest: sha256:f9ccb476e2388efa0dfdf817625a94f2247674148a69b7e4846793e63c8be994 size: 1789

Ahora que ha insertado la imagen de la aplicación en Container Registry, use el siguiente comando para crear una instancia de Container Apps para ejecutar la aplicación después de extraer la imagen de Container Registry:

az containerapp create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $ACA_NAME \
    --image $TODO_QUARKUS_TAG \
    --environment $ACA_ENV \
    --registry-server $LOGIN_SERVER \
    --registry-username $USER_NAME \
    --registry-password $PASSWORD \
    --target-port 8080 \
    --ingress 'external'

La salida correcta es un objeto JSON que incluye la propiedad "type": "Microsoft.App/containerApps".

Obtenga una dirección URL completa para acceder a la aplicación Todo mediante el siguiente comando:

export QUARKUS_URL=https://$(az containerapp show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $ACA_NAME \
    --query properties.configuration.ingress.fqdn -o tsv)
echo $QUARKUS_URL

Abra un nuevo explorador web en el valor de ${QUARKUS_URL}. A continuación, agregue un nuevo elemento de tareas pendientes con el texto Deployed the Todo app to Container Apps. Seleccione este elemento para marcarlo como completado.

Screenshot of the Todo sample app running in Container Apps.

Acceda a la API RESTful (/api) para obtener todos los elementos de tareas pendientes almacenados en Azure Database for PostgreSQL, como se muestra en el ejemplo siguiente:

curl --verbose -k ${QUARKUS_URL}/api | jq .

La salida debería tener un aspecto similar al ejemplo siguiente:

* Connected to <aca-name>.<random-id>.eastus.azurecontainerapps.io (20.231.235.79) port 443 (#0)
> GET /api HTTP/2
> Host: <aca-name>.<random-id>.eastus.azurecontainerapps.io
> user-agent: curl/7.88.1
> accept: */*
>
< HTTP/2 200
< content-length: 88
< content-type: application/json;charset=UTF-8
<
[
  {
    "id": 1,
    "title": "Deployed the Todo app to Container Apps",
    "completed": true,
    "order": 1,
    "url": null
  }
]

Comprobación de que la base de datos se ha actualizado mediante Azure Cloud Shell

Abra Azure Cloud Shell en Azure Portal; para ello, seleccione el icono de Cloud Shell ( ) situado junto al cuadro de búsqueda.

Ejecute el siguiente comando localmente y pegue el resultado en Azure Cloud Shell:

echo psql --host=${DB_SERVER_NAME}.postgres.database.azure.com --port=5432 --username=quarkus@${DB_SERVER_NAME} --dbname=todo

Cuando se le solicite la contraseña, use el valor que empleó al crear la base de datos.

Use la consulta siguiente para obtener todos los elementos de tareas pendientes:

select * from todo;

La salida debe ser similar al ejemplo siguiente y debe incluir los mismos elementos en la GUI de la aplicación de tareas pendientes mostrada anteriormente:

Screenshot of the query output as an ASCII table.

Escriba \q para salir del programa psql y vuelva al Cloud Shell.

Limpieza de recursos

Para evitar los cargos de Azure, se recomienda limpiar los recursos que no sean necesarios. Cuando el clúster ya no se necesite, puede usar el comando az group delete para quitar el grupo de recursos, el servicio de contenedor, el registro de contenedor y todos los recursos relacionados.

git reset --hard
docker rmi ${TODO_QUARKUS_TAG}
az group delete --name $RESOURCE_GROUP_NAME --yes --no-wait

También puede usar docker rmi para eliminar las postgres imágenes de contenedor y testcontainers generadas por el modo de desarrollo de Quarkus.

Pasos siguientes