Relacionamento Digitalcom o Cidadão
Parte V — Tecnologia
Parte V — TecnologiaCapítulo 39

Capítulo 39 — Containers e Empacotamento

Este capítulo detalha a estratégia de empacotamento de componentes da Plataforma de Relacionamento Digital com o Cidadão em containers Docker, cobrindo: construção de imagens, segurança do container, versionamento, distr…

39.1 Objetivo do Capítulo

Este capítulo detalha a estratégia de empacotamento de componentes da Plataforma de Relacionamento Digital com o Cidadão em containers Docker, cobrindo: construção de imagens, segurança do container, versionamento, distribuição, registros privados, scanning de vulnerabilidades, reprodutibilidade e boas práticas operacionais.

O capítulo estabelece como cada serviço é transformado em imagem imutável, verificada, versionada e distribuída para execução em Kubernetes.


39.2 Papel do Empacotamento em Containers

O container é a unidade de deploy da plataforma. Cada serviço, cada ferramenta, cada worker é empacotado como imagem Docker imutável.

Código-fonte versionado (Git)
    │
CI Pipeline (build)
    │
Dockerfile → Docker image
    │
Scanning de vulnerabilidades
    │
Registry privado
    │
Kubernetes pull image
    │
Container em execução

A imagem é o artefato que passa por scanning, é versionado, é armazenado em registry e é implantado.


39.3 Princípios de Empacotamento

  1. Imagens imutáveis — build uma vez, deploy em múltiplos ambientes;
  2. Tamanho mínimo — apenas runtime e dependências necessárias;
  3. Segurança por padrão — sem vulnerabilidades conhecidas, sem secrets, usuário não-root;
  4. Reprodutibilidade — mesmo código-fonte → mesma imagem (bit-for-bit);
  5. Versionamento claro — tag semântica, commit hash, registry;
  6. Scanning obrigatório — antes de aceitar imagem em qualquer ambiente;
  7. Registry único — sem duplicação, controle de acesso centralizado;
  8. Isolamento de camadas — cada camada tem propósito claro e é potencialmente cachevel.

39.4 Docker e Alternativas

39.4.1 Docker como Padrão

Docker é o padrão de container da plataforma. Todas as imagens são construídas com Dockerfile e são conformes com Open Container Initiative (OCI).

39.4.2 Alternativas Avaliadas

TecnologiaCasos de UsoDecisão
PodmanContainers sem daemonNão adotado (Docker é padrão)
BuildahConstrução alternativaNão adotado
containerdRuntime alternativoPossível em Kubernetes (transparente)
unikernel (MirageOS, etc)Segurança extremaNão adotado (overhead operacional)

39.5 Estrutura de Dockerfile

39.5.1 Multi-stage Build

# Stage 1: Construção (build)
FROM maven:3.8-openjdk-21 AS builder

WORKDIR /build
COPY . .
RUN mvn clean package -DskipTests -q

# Stage 2: Runtime (final)
FROM openjdk:21-jdk-slim

# Usuário não-root
RUN groupadd -r appuser && useradd -r -g appuser appuser

# Apenas JAR executável (sem código-fonte)
COPY --from=builder /build/target/app.jar /opt/app/app.jar

# Metadados
LABEL org.opencontainers.image.title="API Solicitações"
LABEL org.opencontainers.image.version="1.2.3"
LABEL org.opencontainers.image.source="https://git.example.com/..."

# Healthcheck
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD java -jar /opt/app/app.jar health

USER appuser
EXPOSE 8080
ENTRYPOINT ["java", "-XX:+UseG1GC", "-Xmx512m", "-jar", "/opt/app/app.jar"]

39.5.2 Boas Práticas

  • Multi-stage: separar build-time de runtime reduz tamanho final;
  • Layer caching: colocar instruções que mudam frequentemente no final;
  • Usuário não-root: NEVER executar container como root;
  • Healthcheck: definir verificação de saúde nativa;
  • Labels: metadados OCI (título, versão, origem);
  • ENTRYPOINT vs. CMD: usar ENTRYPOINT para aplicação principal;
  • Sem secrets: nenhuma chave, token ou senha em Dockerfile ou .dockerignore obrigatório;
  • .dockerignore: excluir .git, node_modules, cache, arquivos de teste, credenciais.
.git
.gitignore
.env
.env.local
node_modules
dist
build
coverage
*.log
.DS_Store

39.6 Imagens Base

39.6.1 Seleção de Base

BaseTamanhoCasosSegurança
openjdk:21-jdk-slim~300MBBackend JavaAtualizada regularmente
node:20-alpine~200MBNode.jsLightweight, Alpine
python:3.12-slim~150MBPythonSlim reduz superfície
alpine:latest~7MBFerramentas, sidecarMuito pequena, minimal

Imagens Alpine reduzem tamanho mas têm menos ferramentas de debug — trade-off entre segurança (menor superfície) e operabilidade.

39.6.2 Versionamento de Base

# ❌ Não fazer (imprevisível)
FROM openjdk:21-jdk-slim

# ✓ Fazer (pinned, reproduzível)
FROM openjdk:21-jdk-slim@sha256:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6

Usar digest SHA256 garante que a mesma imagem base é puxada sempre.


39.7 Build e CI Pipeline

39.7.1 Trigger de Build

Builds são disparados por:

  • push em branch de feature (build, test, scan);
  • merge em main (build, test, scan, push para staging registry);
  • tag de release (build, test, scan, push para production registry).

39.7.2 Pipeline de Build

1. Checkout do código
2. Lint (Dockerfile lint)
3. Build da imagem Docker
4. Scanning de vulnerabilidades (Trivy, Snyk, Grype)
5. Se aprovado:
   a. Tag semântica (v1.2.3, v1.2.3-rc.1)
   b. Tag commit (commit-hash)
   c. Tag latest (apenas em main)
6. Push para registry
7. Atualizar manifesto Kubernetes (Argo CD)

39.7.3 Exemplo: GitHub Actions

name: Build and Push Docker Image

on:
  push:
    branches: [ main, develop ]
    tags: [ 'v*' ]

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - name: Lint Dockerfile
        run: docker run --rm -i hadolint/hadolint < Dockerfile
      
      - name: Build image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: false
          load: true
          tags: app:${{ github.sha }}
      
      - name: Scan with Trivy
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: app:${{ github.sha }}
          format: 'sarif'
          output: 'trivy-results.sarif'
      
      - name: Upload Trivy results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'
      
      - name: Login to Registry
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: registry.example.com
          username: ${{ secrets.REGISTRY_USER }}
          password: ${{ secrets.REGISTRY_TOKEN }}
      
      - name: Build and push
        if: github.event_name != 'pull_request'
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            registry.example.com/platform/app:${{ github.sha }}
            registry.example.com/platform/app:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

39.8 Scanning de Vulnerabilidades

39.8.1 Ferramentas de Scanning

FerramentaCoberturaIntegraçãoCusto
Trivy (Aqua)Imagem, dependências, misconfigCI/CD, KubernetesOpen source
SnykDependências, image, IACCI/CD, IDE, registryFreemium
Grype (Anchore)Imagem, SBOMCI/CD, KubernetesOpen source
ClairImagem registry nativaRegistryOpen source

39.8.2 Política de Scanning

  • Obrigatório: toda imagem é scaneada antes de push para production;
  • Bloqueio: vulnerabilidades críticas bloqueiam deploy;
  • Aprovação: vulnerabilidades altas requerem aprovação manual;
  • Baseline: vulnerabilidades conhecidas são rastreadas (waived com justificativa);
  • Rechecagem: imagens em produção são rescaneadas periodicamente.

39.8.3 Exemplo: Trivy

# Scan de imagem local
trivy image app:v1.2.3

# Scan de Dockerfile antes do build
trivy config Dockerfile

# Exportar SBOM (Software Bill of Materials)
trivy image app:v1.2.3 --format cyclonedx --output sbom.xml

# Scan com severity mínimo
trivy image app:v1.2.3 --severity CRITICAL,HIGH

39.9 Registry Privado

39.9.1 Harbor como Registry

Harbor é o registro privado centralizado. Oferece: RBAC, scanning nativo (Trivy), replicação, quotas, auditoria.

apiVersion: v1
kind: Secret
metadata:
  name: registry-credentials
  namespace: default
type: kubernetes.io/dockercfg
data:
  .dockercfg: eyJyZWdpc3RyeS5leGFtcGxlLmNvbSI6eyJhdXRoIjoiYmFzZTY0LWVuY29kZWQtdXNlcm5hbWU6cGFzc3dvcmQifX0=
---
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  imagePullSecrets:
  - name: registry-credentials
  containers:
  - name: app
    image: registry.example.com/platform/app:v1.2.3

39.9.2 Replicação entre Registries

Harbor replica imagens entre múltiplos datacenters:

# Replicação push para registry de backup
registry.example.com/platform/app:v1.2.3
  ↓
backup-registry.example.com/platform/app:v1.2.3

39.10 Versionamento de Imagens

39.10.1 Estratégia de Tag

registry.example.com/platform/api-solicitacoes:MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]

Exemplos:
  v1.2.3                (release)
  v1.2.3-rc.1           (release candidate)
  v1.2.3-alpha.1        (alpha)
  v1.2.3-SHA256:a1b2c3 (commit hash)
  latest                (sempre aponta para last stable)

39.10.2 Imutabilidade

Tags nunca são sobrescritas em production. Uma vez que v1.2.3 é tagged, sempre referencia a mesma imagem.


39.11 Segurança do Container

39.11.1 Context de Segurança

apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
    readOnlyRootFilesystem: true
  containers:
  - name: app
    image: registry.example.com/platform/app:v1.2.3
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop:
          - ALL
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir:
      medium: Memory

39.11.2 Verificação de Assinatura

Imagens podem ser assinadas e verificadas:

# Sign image
cosign sign --key cosign.key registry.example.com/platform/app:v1.2.3

# Verify
cosign verify --key cosign.pub registry.example.com/platform/app:v1.2.3

39.12 Otimização de Tamanho

39.12.1 Análise de Camadas

# Inspecionar tamanho de cada camada
dive registry.example.com/platform/app:v1.2.3

# Estimativa de tamanho comprimido
docker image inspect registry.example.com/platform/app:v1.2.3 | jq '.Size'

39.12.2 Estratégias de Redução

EstratégiaReduçãoTrade-off
Multi-stage build50-80%Mais complexo
Alpine base70-90%Menos ferramentas de debug
Remover dev deps30-50%Perda de headers, libs
Compress layers10-20%Overhead de descompressão

39.13 Operação de Containers

39.13.1 Limpeza Periódica

# Remover imagens não utilizadas
docker image prune -a

# Remover layers órfãs
docker system prune --all

# Em registry: remover tags antigas
# Harbor oferece policy de retenção

39.13.2 Rotação de Credenciais

Credenciais de registry são rotacionadas conforme política:

# Regenerar token no registry
# Atualizar secret Kubernetes
kubectl patch secret registry-credentials \
  -p '{"data":{".dockercfg":"<new-base64-encoded-token>"}}'

# Redeploy pods para puxar novo token
kubectl rollout restart deployment/api-solicitacoes

39.14 Rastreabilidade com o Anexo III

Item ANX-IIIAtendimento
6.1Containers imutáveis, verificados e versionados
6.2Scanning obrigatório antes de deploy
6.3Auditoria de builds e pushes para registry

39.15 Benefícios do Empacotamento em Containers

  • imagens imutáveis garantem deploy consistente;
  • scanning detecta vulnerabilidades antes de produção;
  • registry centralizado controla acesso e versões;
  • multi-stage reduz tamanho e superfície de ataque;
  • usuário não-root aumenta segurança;
  • healthcheck oferece observabilidade nativa;
  • reprodutibilidade garante parity entre ambientes.

39.16 Riscos e Mitigações

RiscoConsequênciaMitigação
Imagem não verificada em produçãoMalware ou vulnerabilidade não detectadaScan obrigatório antes de push
Secrets em Dockerfile ou imagemExposição de credencialUsar secrets do Kubernetes, nunca em imagem
Base desatualizadaVulnerabilidades conhecidas no SOAtualizar base regularmente, rescan
Tag latest ao vivoImprevisibilidade de qual versão está rodandoUsar tags semânticas, latest apenas para staging
Layer não cacheávelRebuild lento em CI/CDOrdenar instruções para cachear máximo
Imagem gigantePull lento, custo de storageMulti-stage, Alpine, remover build deps

39.17 Decisões Arquiteturais

ADRTema
ADR-601Docker como padrão de container
ADR-602Harbor como registry privado
ADR-603Trivy para scanning de vulnerabilidades
ADR-604Multi-stage build obrigatório
ADR-605Usuário não-root em todos os containers
ADR-606Versionamento semântico de imagens
ADR-607Replicação de imagens entre datacenters
ADR-608Assinatura e verificação de imagens

39.18 Considerações Finais

O container é o artefato que transita da máquina do desenvolvedor para produção. A qualidade, segurança e reprodutibilidade do container determinam a confiabilidade de toda a implantação. Multi-stage builds, scanning obrigatório, usuário não-root e versionamento semântico transformam container de "funciona na minha máquina" em "funciona garantidamente em qualquer lugar".

O Capítulo 40 detalha DevSecOps e Entrega Contínua.


39.19 Controle de Versão

CampoValor
DocumentoDocumento Mestre — Plataforma de Relacionamento Digital com o Cidadão
Capítulo39 — Containers e Empacotamento
Versão1.0
SituaçãoConcluído
Última atualização16/07/2026

39.20 Rastreabilidade PRODEMGE

  • [ANX-III] Bloco 6 — itens 6.1, 6.2, 6.3 cobertos conforme seção 39.14.
  • [ANX-IV] — Capacidades técnicas de container, scanning, registry, CI/CD.
  • [ANX-V] Item 2.1 — Manutenibilidade: Dockerfiles reproducíveis, multi-stage, boas práticas.
  • [PNR] — Containers como unidade de deploy, imutáveis e verificados.
  • [EDITAL] — Edital CP001/2026: containers em Docker, scanning de vulnerabilidades, registry privado, CD automático.

Nesta página