🐳

Docker Images Build & Publish

Docker Images - Build & Publish

📋 Visão Geral

Sistema automatizado de build e publicação de imagens Docker para todos os serviços Audissey, com versionamento semântico e deploy para Azure Container Registry (ACR).

🐳 Imagens Docker

Serviços Disponíveis

1. **API Service** (`audissey-api`)

2. **Worker Service** (`audissey-worker`)

3. **ML Service** (`audissey-ml`)

📦 Versionamento

Sistema de Versões

O projeto usa Semantic Versioning (SemVer):

Arquivo `version.json`

{
  "version": "1.0.0",
  "services": {
    "api": "1.0.0",
    "worker": "1.0.0",
    "ml-service": "0.1.0"
  },
  "lastUpdated": "2025-12-27T00:00:00Z"
}

Script de Bump

# Fazer bump de um serviço específico
./scripts/bump-version.sh api patch      # 1.0.0 -> 1.0.1
./scripts/bump-version.sh worker minor   # 1.0.0 -> 1.1.0
./scripts/bump-version.sh ml-service major # 0.1.0 -> 1.0.0

# Fazer bump de todos os serviços
./scripts/bump-version.sh all patch

Após bump:

# Commit e tag
git add version.json
git commit -m "chore: bump version to v1.0.1"
git tag v1.0.1
git push origin main --tags

🔄 Pipeline CI/CD

Arquivo: `azure-pipelines-docker.yml`

Triggers

Stages

1. Get Version Info

2. Build & Push API

3. Build & Push Worker

4. Build & Push ML

5. Summary

Autenticação das pipelines BuildKit

As pipelines de build usam login direto no audissey.azurecr.io com os
secrets ACR_USERNAME e ACR_PASSWORD do Variable Group audissey-dev.
Este fluxo mantém as credenciais no ~/.docker/config.json, que também é
utilizado pelo driver docker-container do BuildKit. O login Docker@2 não
deve ser reintroduzido nestas builds: ele usa um DOCKER_CONFIG temporário e
pode causar 401 Unauthorized no endpoint OAuth do ACR durante --push ou
--cache-to.

Tags Geradas

Cada imagem recebe tags determinísticas (sem latest):

audissey.azurecr.io/audissey-api:1.0.0
audissey.azurecr.io/audissey-api:123456  (build ID)

🚀 Setup do Azure Container Registry

1. Criar Container Registry

# Variáveis
RESOURCE_GROUP="audissey-shared-rg"
REGISTRY_NAME="audissey"
LOCATION="westeurope"

# Criar ACR
az acr create \
  --resource-group $RESOURCE_GROUP \
  --name $REGISTRY_NAME \
  --sku Basic \
  --admin-enabled true \
  --location $LOCATION

# Verificar
az acr show --name $REGISTRY_NAME --query loginServer
# Output: audissey.azurecr.io

2. Configurar Service Connection no Azure DevOps

Via Portal:

  1. Azure DevOps → Project Settings
  2. Service connections → New service connection
  3. Docker Registry
  4. Registry type: Azure Container Registry
  5. Subscription: Selecionar subscription
  6. Registry: audissey
  7. Service connection name: audissey-acr-connection-shared
  8. Security: Grant access to all pipelines: ❌ NÃO marcar (princípio do menor privilégio)
  9. Save

Autorizar pipelines específicos:

Via CLI:

# Get ACR credentials
ACR_USER=$(az acr credential show --name $REGISTRY_NAME --query username -o tsv)
ACR_PASSWORD=$(az acr credential show --name $REGISTRY_NAME --query passwords[0].value -o tsv)

echo "Username: $ACR_USER"
echo "Password: $ACR_PASSWORD"

# Usar no Azure DevOps

3. Criar Pipeline

  1. Azure DevOps → Pipelines → New Pipeline
  2. Selecionar repositório
  3. Existing Azure Pipelines YAML file
  4. Path: /azure-pipelines-docker.yml
  5. Save and Run

🔧 Build Local

API

# Build
docker build -t audissey-api:dev \
  --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  --build-arg VERSION=dev \
  --build-arg VCS_REF=$(git rev-parse --short HEAD) \
  -f Dockerfile .

# Run
docker run -p 3000:3000 \
  -e MONGO_URI="mongodb://host.docker.internal:27017/audissey" \
  -e REDIS_URL="redis://host.docker.internal:6379" \
  audissey-api:dev

Worker

# Build
docker build -t audissey-worker:dev \
  --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  --build-arg VERSION=dev \
  -f Dockerfile.worker .

# Run
docker run -p 3001:3001 \
  -e MONGO_URI="mongodb://host.docker.internal:27017/audissey" \
  -e REDIS_URL="redis://host.docker.internal:6379" \
  audissey-worker:dev

ML Service

# Build
cd apps/ml-service
docker build -t audissey-ml:dev \
  --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  --build-arg VERSION=dev \
  .

# Run
docker run -p 8000:8000 \
  -e MONGO_URI="mongodb://host.docker.internal:27017/audissey" \
  audissey-ml:dev

📊 Metadata & Labels

Todas as imagens incluem OCI labels para rastreabilidade:

LABEL org.opencontainers.image.title="Audissey API"
LABEL org.opencontainers.image.description="Audissey REST API Service"
LABEL org.opencontainers.image.vendor="Audissey"
LABEL org.opencontainers.image.created="2025-12-27T10:30:00Z"
LABEL org.opencontainers.image.version="1.0.0"
LABEL org.opencontainers.image.revision="abc1234"

ARG BUILD_DATE, VERSION e VCS_REF ficam no fim do stage, depois do último RUN: mudam a cada build, e um RUN abaixo deles falha a cache e volta a enviar as layers para o ACR. scripts/node-version-alignment.test.js falha se voltarem para cima. Ver "Storage do ACR" em ENVIRONMENTS.md.

Inspecionar metadata:

docker image inspect audissey.azurecr.io/audissey-api:1.0.0 \
  --format='{{json .Config.Labels}}' | jq

🔍 Gerenciar Imagens no ACR

Listar Imagens

# Listar repositórios
az acr repository list --name audissey --output table

# Listar tags de uma imagem
az acr repository show-tags --name audissey \
  --repository audissey-api \
  --orderby time_desc \
  --output table

Pull de Imagem

# Login no ACR
az acr login --name audissey

# Pull
docker pull audissey.azurecr.io/audissey-api:1.0.0
docker pull audissey.azurecr.io/audissey-worker:1.0.0
docker pull audissey.azurecr.io/audissey-ml:0.1.0

Deletar Imagens Antigas

O que apagar, e o que nunca apagar, está em "Storage do ACR" em ENVIRONMENTS.md. Os dados apagados não se recuperam: correr sempre primeiro com --dry-run.

# Só manifests sem tag com mais de 7 dias. Não toca em nenhuma tag.
az acr run --registry audissey --timeout 3600 \
  --cmd "acr purge --untagged-only --ago 7d --dry-run" /dev/null

Não usar show-tags | xargs az acr repository delete: cada build tem duas tags, a ordenação inclui buildcache e nada protege as imagens em uso.

🚀 Deploy com Docker Images

Azure App Service

# Configurar App Service para usar imagem do ACR
# Nota: no setup atual recomenda-se pull via Managed Identity + role AcrPull (sem ACR admin user).
az webapp config container set \
  --name audissey-api \
  --resource-group audissey-rg \
  --docker-custom-image-name audissey.azurecr.io/audissey-api:1.0.0 \
  --docker-registry-server-url https://audissey.azurecr.io

Azure Container Apps (Worker)

# Update da imagem do Worker (Container App)
# O Worker não precisa de ingress; secrets tipicamente vêm de Key Vault refs (secretref).
az containerapp update \
  --resource-group audissey-dev-rg \
  --name audissey-worker-dev \
  --image audissey.azurecr.io/audissey-worker:1.0.0

Docker Compose (Local)

version: '3.8'
services:
  api:
    image: audissey.azurecr.io/audissey-api:1.0.0
    ports:
      - '3000:3000'
    environment:
      - MONGO_URI=mongodb://mongo:27017/audissey
      - REDIS_URL=redis://redis:6379

  worker:
    image: audissey.azurecr.io/audissey-worker:1.0.0
    environment:
      - MONGO_URI=mongodb://mongo:27017/audissey
      - REDIS_URL=redis://redis:6379

  ml:
    image: audissey.azurecr.io/audissey-ml:0.1.0
    ports:
      - '8000:8000'
    environment:
      - MONGO_URI=mongodb://mongo:27017/audissey

🔐 Segurança

Scan de Vulnerabilidades

# Scan com Microsoft Defender for Cloud (integrado no ACR)
az acr task create \
  --name vulnerabilityScan \
  --registry audissey \
  --context /dev/null \
  --cmd "mcr.microsoft.com/azure-cli" \
  --schedule "0 0 * * *"

Políticas de Retenção

# Manter apenas últimas 10 imagens
az acr config retention update \
  --registry audissey \
  --status enabled \
  --days 30 \
  --type UntaggedManifests

📝 Workflow Completo

1. Desenvolvimento

# Fazer mudanças
git checkout -b feature/new-endpoint
# ... desenvolver ...
git commit -m "feat: adicionar novo endpoint"

2. Versionamento

# Bump version
./scripts/bump-version.sh api patch

# Commit version
git add version.json
git commit -m "chore: bump API version to 1.0.1"

3. Merge para Main

# Criar PR e merge para main
git push origin feature/new-endpoint
# Abrir PR no Azure DevOps
# Aguardar aprovação e merge

4. Pipeline Automático

5. Tag Release

# Após merge bem-sucedido
git checkout main
git pull
git tag v1.0.1
git push origin v1.0.1

📚 Recursos


Última atualização: 27 de dezembro de 2025