Pular para o conteúdo principal

Desafio 06: Implantação em Contêiner para IA

Tempo Estimado

45-60 min | Custo: ~$0.50 (contêiner ainda é cobrado no Azure) | Domínio: Planejar e Gerenciar Soluções de IA (20-25%)

Habilidades do exame cobertas

  • Planejar e implementar implantação em contêiner para Azure AI services
  • Configurar contêineres desconectados para cenários de borda
  • Gerenciar requisitos de licenciamento e cobrança de contêineres

Visão Geral

Os Azure AI services podem ser implantados como contêineres Docker, permitindo que você execute capacidades de IA on-premises, na borda ou em ambientes desconectados. Embora os contêineres sejam executados localmente, eles ainda requerem uma conexão com o Azure para fins de cobrança, a menos que estejam configurados para o modo desconectado.

A implantação em contêiner é crítica para cenários que exigem residência de dados, baixa latência ou conectividade intermitente. Você trabalhará com contêineres de detecção de idioma e análise de sentimento, aprendendo como baixar imagens do Microsoft Container Registry, configurar endpoints de cobrança e validar a saúde do contêiner.

Entender o modelo de cobrança é essencial — os contêineres precisam se comunicar com o Azure para medição mesmo quando processam dados localmente, a menos que você tenha obtido uma licença de contêiner desconectado por meio de um processo de aprovação.

Arquitetura

A implantação em contêiner conecta contêineres Docker locais aos Azure AI services para cobrança enquanto processa dados localmente.

Challenge 06 topology

Pré-requisitos

  • Assinatura do Azure com um recurso multi-serviço de Azure AI services
  • Docker Desktop instalado e em execução
  • Azure CLI instalado
  • Pelo menos 8 GB de RAM disponível para contêineres
  • Endpoint e chave do seu recurso Azure AI services

Implementação

Tarefa 1: Criar Recurso Azure AI Services para Cobrança

from azure.identity import DefaultAzureCredential
from azure.mgmt.cognitiveservices import CognitiveServicesManagementClient
from azure.mgmt.cognitiveservices.models import Account, Sku

credential = DefaultAzureCredential()
client = CognitiveServicesManagementClient(credential, subscription_id="<your-subscription-id>")

# Create a multi-service resource for container billing
account = client.accounts.begin_create(
resource_group_name="rg-ai102-challenge06",
account_name="ai-containers-billing",
account=Account(
sku=Sku(name="S0"),
kind="AIServices",
location="eastus",
properties={}
)
).result()

print(f"Resource created: {account.name}")
print(f"Endpoint: {account.properties.endpoint}")

# Retrieve keys for container billing configuration
keys = client.accounts.list_keys(
resource_group_name="rg-ai102-challenge06",
account_name="ai-containers-billing"
)
print(f"Key1: {keys.key1}")

Tarefa 2: Baixar e Executar Contêiner de Detecção de Idioma

import subprocess
import requests
import time
import os

ENDPOINT = os.environ["AZURE_AI_ENDPOINT"]
KEY = os.environ["AZURE_AI_KEY"]

# Pull the language detection container
subprocess.run([
"docker", "pull",
"mcr.microsoft.com/azure-cognitive-services/textanalytics/language:latest"
], check=True)

# Run the container with billing configuration
container_id = subprocess.run([
"docker", "run", "-d",
"--name", "language-detection",
"-p", "5000:5000",
"-e", f"Eula=accept",
"-e", f"Billing={ENDPOINT}",
"-e", f"ApiKey={KEY}",
"--memory", "4g",
"--cpus", "2",
"mcr.microsoft.com/azure-cognitive-services/textanalytics/language:latest"
], capture_output=True, text=True, check=True)

print(f"Container started: {container_id.stdout.strip()}")

# Wait for container to be ready
time.sleep(30)

# Health check
response = requests.get("http://localhost:5000/status")
print(f"Container health: {response.json()}")

Tarefa 3: Testar Contêiner de Detecção de Idioma Localmente

from azure.ai.textanalytics import TextAnalyticsClient
from azure.core.credentials import AzureKeyCredential

# Point the SDK client at the local container
# The container exposes the same API as the cloud service
client = TextAnalyticsClient(
endpoint="http://localhost:5000",
credential=AzureKeyCredential("not-needed-for-local")
)

documents = [
"Hello, this is a test document in English.",
"Bonjour, ceci est un document de test en français.",
"Hola, este es un documento de prueba en español.",
"Dies ist ein Testdokument auf Deutsch.",
"これはテスト用のドキュメントです。"
]

response = client.detect_language(documents=documents)

for doc in response:
if not doc.is_error:
print(f"Text: '{doc.input[:40]}...'")
print(f" Language: {doc.primary_language.name}")
print(f" ISO Code: {doc.primary_language.iso6391_name}")
print(f" Confidence: {doc.primary_language.confidence_score:.2f}")
else:
print(f"Error: {doc.error.message}")

Tarefa 4: Executar Contêiner de Análise de Sentimento e Configurar Docker Compose

import yaml
import os

ENDPOINT = os.environ["AZURE_AI_ENDPOINT"]
KEY = os.environ["AZURE_AI_KEY"]

# Generate docker-compose.yml for multi-container deployment
compose_config = {
"version": "3.8",
"services": {
"language-detection": {
"image": "mcr.microsoft.com/azure-cognitive-services/textanalytics/language:latest",
"ports": ["5000:5000"],
"environment": {
"Eula": "accept",
"Billing": ENDPOINT,
"ApiKey": KEY
},
"deploy": {
"resources": {
"limits": {"cpus": "2", "memory": "4G"},
"reservations": {"cpus": "1", "memory": "2G"}
}
},
"healthcheck": {
"test": ["CMD", "curl", "-f", "http://localhost:5000/status"],
"interval": "30s",
"timeout": "10s",
"retries": 3,
"start_period": "60s"
}
},
"sentiment-analysis": {
"image": "mcr.microsoft.com/azure-cognitive-services/textanalytics/sentiment:latest",
"ports": ["5001:5000"],
"environment": {
"Eula": "accept",
"Billing": ENDPOINT,
"ApiKey": KEY
},
"deploy": {
"resources": {
"limits": {"cpus": "2", "memory": "4G"},
"reservations": {"cpus": "1", "memory": "2G"}
}
},
"healthcheck": {
"test": ["CMD", "curl", "-f", "http://localhost:5000/status"],
"interval": "30s",
"timeout": "10s",
"retries": 3,
"start_period": "60s"
}
}
}
}

with open("docker-compose.yml", "w") as f:
yaml.dump(compose_config, f, default_flow_style=False)

print("docker-compose.yml generated")
print("Run: docker compose up -d")

Tarefa 5: Configurar Modo de Contêiner Desconectado

import subprocess
import os

# Note: Disconnected containers require a commitment plan and gating approval
# from Microsoft. This shows the configuration once approved.

# Download the disconnected container license
# (Obtained from Azure portal after gating approval)
LICENSE_PATH = "/path/to/license/file.lic"

# For disconnected mode, the container is configured with:
# - DownloadLicense=True to download the license initially
# - Mounts: volume for license file persistence

# Step 1: Download license (requires initial connectivity)
print("Step 1: Downloading disconnected container license...")
subprocess.run([
"docker", "run", "-d",
"--name", "language-download-license",
"-e", "Eula=accept",
"-e", f"Billing={os.environ['AZURE_AI_ENDPOINT']}",
"-e", f"ApiKey={os.environ['AZURE_AI_KEY']}",
"-e", "DownloadLicense=True",
"-v", "license-data:/license",
"-e", "Containers:Billing:License:Mount=/license",
"mcr.microsoft.com/azure-cognitive-services/textanalytics/language:latest"
], check=True)

print("License downloaded. Container can now run disconnected.")

# Step 2: Run in disconnected mode (no internet required)
print("\nStep 2: Running in disconnected mode...")
subprocess.run([
"docker", "run", "-d",
"--name", "language-disconnected",
"-p", "5000:5000",
"-e", "Eula=accept",
"-v", "license-data:/license",
"-e", "Containers:Billing:License:Mount=/license",
"--network", "none", # No network access - truly disconnected
"mcr.microsoft.com/azure-cognitive-services/textanalytics/language:latest"
], check=True)

print("Container running in disconnected mode (no network).")
print("License validity period: defined by commitment plan duration.")

Saída Esperada

// Language detection response from local container
{
"documents": [
{
"id": "1",
"detectedLanguage": {
"name": "English",
"iso6391Name": "en",
"confidenceScore": 1.0
}
},
{
"id": "2",
"detectedLanguage": {
"name": "French",
"iso6391Name": "fr",
"confidenceScore": 1.0
}
}
]
}

// Container health check
{
"service": "Language",
"status": "ready",
"apiStatus": "Valid",
"apiStatusMessage": "Api Key is valid."
}

Quebra & conserta

CenárioSintomaCausa RaizCorreção
Contêiner não iniciaCódigo de saída 1, "Billing endpoint required"Variável de ambiente Billing ausenteAdicione -e Billing=<endpoint> ao docker run
Contêiner inicia mas retorna 401HTTP 401 em todas as requisiçõesChave API inválida ou ausenteVerifique se a variável de ambiente ApiKey corresponde à chave do recurso Azure
Contêiner crasha com OOMCódigo de saída 137Memória insuficiente alocadaAumente --memory para pelo menos 4g para contêineres de text analytics
Validação de cobrança falha"Unable to reach billing endpoint"Firewall bloqueando HTTPS de saídaPermita saída para *.cognitiveservices.azure.com na porta 443
Licença do contêiner desconectado expirouErro "License expired" na inicializaçãoPeríodo do plano de compromisso encerradoReconecte ao Azure para renovar a licença, ou renove o plano de compromisso

Verificação de Conhecimento

1. O que é necessário para um contêiner Azure AI funcionar no modo conectado?

2. Qual parâmetro Docker deve ser definido como true ao aceitar o contrato de licença do contêiner?

3. Qual é a RAM mínima recomendada para executar o contêiner de detecção de idioma do Text Analytics?

4. Como um contêiner Azure AI desconectado lida com a cobrança?

5. Qual endpoint você pode usar para verificar se um contêiner Azure AI está saudável e pronto para aceitar requisições?

Limpeza

# Stop and remove containers
docker stop language-detection sentiment-analysis language-disconnected 2>/dev/null
docker rm language-detection sentiment-analysis language-disconnected language-download-license 2>/dev/null

# Remove Docker volume
docker volume rm license-data 2>/dev/null

# Remove Azure resources
az group delete --name rg-ai102-challenge06 --yes --no-wait

Saiba Mais