Exercício - Implantar um aplicativo Spring AI nos Aplicativos de Contêiner do Azure
Nesta unidade, você implantará seu aplicativo Spring AI nos Aplicativos de Contêiner do Azure para hospedagem de contêiner escalonável e sem servidor.
Configurar variáveis de ambiente
Para este exercício, você precisa de algumas variáveis de ambiente de exercícios anteriores. Se você estiver usando a mesma janela bash, essas variáveis ainda deverão existir. Se as variáveis não estiverem mais disponíveis, use os comandos a seguir para recriá-las. Certifique-se de substituir os <...> marcadores de posição por seus próprios valores e utilize os mesmos valores que usou anteriormente.
export RESOURCE_GROUP=<resource-group>
export LOCATION=<location>
export OPENAI_RESOURCE_NAME=OpenAISpringAI
export AZURE_OPENAI_ENDPOINT=$(az cognitiveservices account show \
--resource-group $RESOURCE_GROUP \
--name $OPENAI_RESOURCE_NAME \
--query "properties.endpoint" \
--output tsv \
| tr -d '\r')
export AZURE_OPENAI_API_KEY=$(az cognitiveservices account keys list \
--resource-group $RESOURCE_GROUP \
--name $OPENAI_RESOURCE_NAME \
--query "key1" \
--output tsv \
| tr -d '\r')
export DB_SERVER_NAME=<server-name>
export PGHOST=$(az postgres flexible-server show \
--resource-group $RESOURCE_GROUP \
--name $DB_SERVER_NAME \
--query fullyQualifiedDomainName \
--output tsv \
| tr -d '\r')
Você também precisa de algumas variáveis de ambiente novas para esta unidade. Use o comando a seguir para definir essas variáveis. Substitua os espaços reservados <...> pelos seus valores.
export CONTAINER_APP_NAME=<container-app-name>
export MANAGED_IDENTITY_NAME=<managed-identity-name>
export ENVIRONMENT=<Azure-Container-Apps-environment>
Com essas variáveis de ambiente em vigor, agora você está pronto para implantar o aplicativo nos Aplicativos de Contêiner do Azure.
Criar um Dockerfile
Em seguida, crie um Dockerfile e adicione o conteúdo a seguir. Esse arquivo é usado para criar uma imagem do Docker com o código do aplicativo para implantação nos Aplicativos de Contêiner do Azure.
# Step 1: Use microsoft JDK image with maven3 to build the application
FROM mcr.microsoft.com/openjdk/jdk:17-mariner AS builder
RUN tdnf install maven3 -y
WORKDIR /app
COPY pom.xml ./
COPY src ./src
RUN mvn clean package -DskipTests
# Step 2: Use microsoft JDK image for the final image
FROM mcr.microsoft.com/openjdk/jdk:17-mariner
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
Implantar o aplicativo de contêiner
Para implantar o aplicativo, use o seguinte comando:
az containerapp up \
--resource-group $RESOURCE_GROUP \
--name $CONTAINER_APP_NAME \
--environment $ENVIRONMENT \
--source . \
--ingress external \
--target-port 8080 \
--location $LOCATION
Este comando executa as seguintes tarefas:
- Cria o grupo de recursos, se ele ainda não existir.
- Cria o ambiente de Aplicativos de Contêiner com um workspace do Log Analytics. O ambiente é nomeado usando o valor especificado no
environmentparâmetro. - Cria uma instância do Registro de Contêiner do Azure.
- Cria a imagem de contêiner usando o código-fonte e o Dockerfile no diretório especificado pelo
sourceparâmetro e, em seguida, envia-a por push para o registro. - Cria e implanta o aplicativo de contêiner usando a imagem de contêiner criada. O aplicativo de contêiner é nomeado usando o valor especificado no
nameparâmetro. - Configura
8080como a porta HTTP que o aplicativo de contêiner usa para escutar o tráfego de entrada. - Implanta o aplicativo de contêiner na região especificada no
locationparâmetro.
Para exibir os logs do aplicativo de contêiner, use o seguinte comando:
az containerapp logs show \
--resource-group $RESOURCE_GROUP \
--name $CONTAINER_APP_NAME \
--tail 80
O exemplo a seguir mostra um log típico. Ao inspecionar os logs, você pode ver que o aplicativo não está iniciando com êxito devido a valores de configuração ausentes, o que é esperado neste momento.
{"TimeStamp": "2025-03-04T19:04:52.7673831+00:00", "Log": "F Caused by: org.postgresql.util.PSQLException:
FATAL: Azure AD user token for role[AzureAdmin] is neither an AAD_AUTH_TOKENTYPE_APP_USER or an
AAD_AUTH_TOKENTYPE_APP_OBO token."}
Para reimplantar o aplicativo depois de fazer alterações, você pode usar o seguinte comando:
az containerapp update \
--resource-group $RESOURCE_GROUP \
--name $CONTAINER_APP_NAME \
--source .
Habilitar a identidade gerenciada
O aplicativo de contêiner precisa ser capaz de se autenticar no servidor PostgresSQL. Você usa identidades gerenciadas atribuídas pelo sistema para autenticação.
Para habilitar uma identidade gerenciada atribuída pelo sistema para seu aplicativo de contêiner, use o seguinte comando:
az containerapp identity assign \
--resource-group $RESOURCE_GROUP \
--name $CONTAINER_APP_NAME \
--system-assigned
Para obter a ID da identidade gerenciada atribuída pelo sistema e exibi-la, use os seguintes comandos:
export MANAGED_IDENTITY_ID=$(az containerapp show \
--resource-group $RESOURCE_GROUP \
--name $CONTAINER_APP_NAME \
--query 'identity.principalId' \
--output tsv \
| tr -d '\r')
echo "Managed Identity ID: $MANAGED_IDENTITY_ID"
Para autorizar a identidade gerenciada do seu aplicativo de contêiner a acessar o Azure Database for PostgreSQL no servidor flexível, use o seguinte comando:
az postgres flexible-server ad-admin create \
--resource-group $RESOURCE_GROUP \
--server-name $DB_SERVER_NAME \
--display-name $MANAGED_IDENTITY_NAME \
--object-id $MANAGED_IDENTITY_ID \
--type ServicePrincipal
Configurar o ambiente do aplicativo de contêiner e o segredo
Para criar um segredo para valores confidenciais, use o seguinte comando:
az containerapp secret set \
--resource-group $RESOURCE_GROUP \
--name $CONTAINER_APP_NAME \
--secrets \
azure-openai-api-key=$AZURE_OPENAI_API_KEY
Em seguida, use o seguinte comando para definir variáveis de ambiente:
az containerapp update \
--resource-group $RESOURCE_GROUP \
--name $CONTAINER_APP_NAME \
--set-env-vars \
SPRING_AI_AZURE_OPENAI_API_KEY=secretref:azure-openai-api-key \
SPRING_AI_AZURE_OPENAI_ENDPOINT=${AZURE_OPENAI_ENDPOINT} \
SPRING_DATASOURCE_USERNAME=${MANAGED_IDENTITY_NAME} \
SPRING_DATASOURCE_URL=jdbc:postgresql://${PGHOST}/postgres?sslmode=require \
SPRING_AI_VECTORSTORE_PGVECTOR_SCHEMA_NAME=containerapp
Esse comando usa intencionalmente um nome de esquema diferente pgvector para evitar conflitos de usar o mesmo nome de esquema com um usuário diferente.
Verificar a implantação
Use o seguinte comando para obter a URL do aplicativo de contêiner:
export URL=$(az containerapp show \
--resource-group $RESOURCE_GROUP \
--name $CONTAINER_APP_NAME \
--query properties.configuration.ingress.fqdn \
--output tsv)
Use o seguinte comando para testar o endpoint:
curl -G "https://$URL/api/rag" \
--data-urlencode "query=How does QuestionAnswerAdvisor work in Spring AI?"
A resposta deve ser semelhante ao seguinte exemplo:
In the context of **Spring AI**, the **QuestionAnswerAdvisor** operates as a key component for enabling **Retrieval Augmented Generation (RAG)**, which combines user queries with external contextual data to produce accurate and relevant AI responses.
Use o seguinte comando para tentar outra pergunta que não esteja no repositório de vetores:
curl -G "https://$URL/api/rag" \
--data-urlencode "query=What is vector similarity search?"
A resposta deve ser semelhante ao seguinte exemplo:
**Vector similarity search** refers to the process of comparing and ranking data points - represented as vectors - based on their similarity in a multi-dimensional space. This method is commonly used in applications like information retrieval, recommendation systems, natural language processing, and computer vision.
Use o seguinte comando para testar o endpoint de geração de blogs:
curl -G "https://$URL/api/blog" \
--data-urlencode "topic=Java on Azure"
Devido ao ciclo de iteração de revisão, essa solicitação leva mais tempo para ser concluída. Após a conclusão, você deverá ver uma resposta JSON contendo o conteúdo do blog e os metadados sobre o processo de geração, conforme mostrado no exemplo a seguir:
{
"metadata": {
"totalTokensUsed": 8637,
"approved": false,
"tokenUsage": {
"promptTokens": 5324,
"totalTokens": 8637,
"completionTokens": 3313
},
"model": "Azure OpenAI",
"editorFeedback": [
{
"feedback": "**Feedback:**\n\n1. **Sentence Count Issue:** The draft exceeds the strict 10-sentence maximum requirement. It contains 11 sentences. To comply with the rules, you need to condense the content without losing essential details.\n\n2. **Clarity and Flow of Ideas:** While the draft is informative, the transition between sections feels slightly mechanical. For instance, the sentence about deploying a Spring Boot application being simple could flow better into the discussion about monitoring and diagnostics. Consider smoothing out these transitions to make the blog more cohesive.\n\n3. **Engagement and Reader Interest:** The tone is professional but lacks a conversational spark that would fully engage the reader. Adding a brief anecdote, rhetorical question, or vivid example could help draw readers in. For example, you could open with a scenario like, \"Imagine deploying your Java app to the cloud in minutes, while Azure handles the heavy lifting.\"\n\n4. **Professional Yet Conversational Tone:** While polished, the tone leans slightly towards technical documentation rather than a conversational blog. Use more approachable phrasing to make it relatable to broader audiences, such as developers exploring Azure for the first time.\n\n5. **Structure and Organization:** The draft provides valuable information but feels slightly dense. Breaking it into smaller, more digestible sections or trimming less critical details can improve readability. For example, you could consolidate the points about Azure's tools and services into a single sentence to save space.\n\n6. **Actionable Suggestions:**\n - Reduce sentence count to meet the 10-sentence maximum by combining or trimming redundant ideas. For example, integrate the points about Azure's services and Spring Boot deployment into a single concise statement.\n - Add a conversational hook or engaging opening sentence to draw readers in immediately.\n - Improve transitions between ideas to enhance flow and readability. For instance, connect the infrastructure management point more naturally to the monitoring and diagnostics capabilities.\n - Consider rephrasing to strike a balance between technical detail and approachable language.\n\n7. **Conclusion Improvement:** The conclusion is strong but could be more dynamic. Consider ending with a forward-looking statement or call-to-action, such as, \"Explore how Azure can revolutionize your Java development journey today.\"\n\nBy implementing these changes, the blog can achieve a more refined, engaging, and reader-friendly result while adhering to the rules.",
"iteration": 1
},
{
"feedback": "**Feedback:**\n\n1. **Sentence Count:** The draft contains 11 sentences, exceeding the 10-sentence limit. This violates the stated guidelines and must be corrected. Revising for conciseness is necessary.\n\n2. **Clarity and Flow:** While the ideas are clear, the flow feels slightly disjointed. The transitions between Java frameworks, tools, and Azure services could be smoother to create a more cohesive narrative. Consider linking sections with transitional phrases to enhance readability.\n\n3. **Engagement and Reader Interest:** The opening sentence is engaging but could be more specific to immediately hook the reader. For example, instead of \"Imagine deploying your Java app to the cloud,\" consider adding a concrete benefit or scenario that resonates with developers.\n\n4. **Professional yet Conversational Tone:** The tone is professional but leans too heavily on technical descriptions without enough conversational elements. Adding relatable examples or posing direct questions might make the blog more inviting.\n\n5. **Structure and Organization:** The structure is logical but somewhat crowded. Too many points are packed into a small space, leading to information overload. Break the content into digestible chunks and prioritize key ideas.\n\n6. **Adherence to the 10-Sentence Limit:** Beyond trimming the number of sentences, ensure each sentence delivers maximum impact. Avoid redundancy, such as mentioning \"Azure manages infrastructure effortlessly\" and \"Azure supports popular Java frameworks to simplify your development journey,\" which overlap conceptually.\n\n7. **Suggestions for Improvement:**\n - Reduce sentence count to meet the 10-sentence limit while retaining the essential points.\n - Strengthen transitions to improve flow.\n - Rewrite the opening sentence to include a more compelling example or benefit.\n - Focus on fewer Azure services for clarity and emphasize their unique value instead of listing too many features.\n - Add a more engaging closing statement that calls the reader to action or leaves a memorable impression.\n\n**Actionable Revision Steps:**\n- Consolidate redundant ideas.\n- Use a more concise, focused approach to highlight Azure's benefits for Java developers.\n- Revise for a conversational yet professional tone that balances technical details with reader engagement.\n\nThis draft shows promise but requires significant refinement to meet the strict evaluation standards.",
"iteration": 2
},
{
"feedback": "Here is my detailed feedback on the draft:\n\n1. **Sentence Count**: The blog draft contains **10 sentences**, meeting the sentence limit requirement. However, adhering to the rule that all first iterations must receive a NEEDS_IMPROVEMENT rating, the draft will be evaluated critically.\n\n2. **Clarity and Flow of Ideas**: The draft is clear and flows logically, but it lacks specificity in some areas. For instance, phrases like \"Azure simplifies the process\" and \"streamline development workflows\" are somewhat vague. Readers may appreciate concrete examples or brief technical details to substantiate these claims. For example, how exactly does the integration with IntelliJ IDEA streamline workflows?\n\n3. **Engagement and Reader Interest**: While the draft is informative, it could enhance engagement by including a compelling hook. The opening sentence is functional but lacks the punch to immediately captivate readers. Consider starting with a thought-provoking question, statistic, or anecdote tied to Java and cloud computing.\n\n4. **Tone**: The tone is professional yet conversational, which works well for the target audience. However, certain phrases like \"letting you focus on what matters most—your code\" feel slightly generic. Adding a more nuanced observation tailored to Java developers could elevate the tone further.\n\n5. **Structure and Organization**: The structure is solid, but the final call-to-action (\"Ready to take your Java projects to the next level?\") is abrupt and lacks a sense of closure. A stronger conclusion could summarize the benefits discussed and tie them back to the opening idea, creating a more cohesive experience.\n\n6. **Suggestions for Improvement**: \n - Add more specificity to claims about Azure's tools and services to make the draft more actionable and informative. \n - Craft a more engaging opening sentence to draw readers in immediately. \n - Refine the conclusion to provide a sense of completion and reinforce the value proposition. \n - Consider rephrasing generic statements to better resonate with the Java developer audience. \n\nOverall, the draft has potential but needs refinement in its engagement techniques, specificity, and structural polish.",
"iteration": 3
}
],
"iterations": 3
},
"topic": "Java on Azure",
"content": "JAVA ON AZURE \n\nWhat if deploying your Java app to the cloud was as simple as a few clicks, instantly connecting you to millions of users worldwide? Java, the backbone of enterprise software development, pairs effortlessly with Microsoft Azure to transform how developers create, deploy, and scale cloud applications. Whether you're crafting microservices with Spring Boot or managing enterprise systems with Jakarta EE, Azure empowers you with tools and services designed for speed and reliability. \n\nTake IntelliJ IDEA integration, for example—it streamlines workflows by enabling developers to deploy directly from their IDE, eliminating the need for complex manual setups. Azure App Service simplifies operations even further, allowing you to publish Spring Boot applications with minimal configuration, while Azure Kubernetes Service (AKS) handles container orchestration seamlessly. These features let you focus on writing clean, efficient code without getting bogged down by infrastructure concerns. \n\nAzure also ensures your applications perform flawlessly with Application Insights, providing end-to-end monitoring for debugging and optimization. Built-in security measures like compliance certifications and encryption safeguard your data, while the pay-as-you-go pricing model lets you scale intelligently based on project demands. \n\nWith Azure, Java developers can embrace a cloud-first future without compromising on efficiency or control. Ready to unlock new possibilities for your Java projects? Explore how Azure can revolutionize your development journey today. "
}
Dimensionar Aplicativos de Contêiner do Azure
Por padrão, seu aplicativo de contêiner é configurado para usar zero réplicas mínimas e uma regra de dimensionamento HTTP para lidar com 10 solicitações por réplica. Para configurar a configuração de dimensionamento, use o seguinte comando:
az containerapp update \
--resource-group $RESOURCE_GROUP \
--name $CONTAINER_APP_NAME \
--min-replicas 1 \
--max-replicas 10 \
--scale-rule-name http-scaler \
--scale-rule-type http \
--scale-rule-http-concurrency 15
Limpeza
Depois de concluir o teste, use os seguintes comandos para remover recursos:
az group delete \
--name $RESOURCE_GROUP \
--yes \
--no-wait
Resumo da unidade
Nesta unidade, você implantou com êxito um aplicativo Spring AI nos Aplicativos de Contêiner do Azure, usando hospedagem de contêiner escalonável e sem servidor. Você configurou as variáveis de ambiente necessárias, criou um Dockerfile para criar a imagem do aplicativo e implantou o aplicativo de contêiner usando comandos da CLI do Azure. Você habilitou a identidade gerenciada para autenticação segura no servidor PostgreSQL e configurou segredos e variáveis de ambiente para o aplicativo. Por fim, você verificou a implantação testando o endpoint do aplicativo e aprendeu a limpar os recursos após os testes.