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
- Imagens imutáveis — build uma vez, deploy em múltiplos ambientes;
- Tamanho mínimo — apenas runtime e dependências necessárias;
- Segurança por padrão — sem vulnerabilidades conhecidas, sem secrets, usuário não-root;
- Reprodutibilidade — mesmo código-fonte → mesma imagem (bit-for-bit);
- Versionamento claro — tag semântica, commit hash, registry;
- Scanning obrigatório — antes de aceitar imagem em qualquer ambiente;
- Registry único — sem duplicação, controle de acesso centralizado;
- 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
| Tecnologia | Casos de Uso | Decisão |
|---|---|---|
| Podman | Containers sem daemon | Não adotado (Docker é padrão) |
| Buildah | Construção alternativa | Não adotado |
| containerd | Runtime alternativo | Possível em Kubernetes (transparente) |
| unikernel (MirageOS, etc) | Segurança extrema | Nã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
| Base | Tamanho | Casos | Segurança |
|---|---|---|---|
openjdk:21-jdk-slim | ~300MB | Backend Java | Atualizada regularmente |
node:20-alpine | ~200MB | Node.js | Lightweight, Alpine |
python:3.12-slim | ~150MB | Python | Slim reduz superfície |
alpine:latest | ~7MB | Ferramentas, sidecar | Muito 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
| Ferramenta | Cobertura | Integração | Custo |
|---|---|---|---|
| Trivy (Aqua) | Imagem, dependências, misconfig | CI/CD, Kubernetes | Open source |
| Snyk | Dependências, image, IAC | CI/CD, IDE, registry | Freemium |
| Grype (Anchore) | Imagem, SBOM | CI/CD, Kubernetes | Open source |
| Clair | Imagem registry nativa | Registry | Open 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égia | Redução | Trade-off |
|---|---|---|
| Multi-stage build | 50-80% | Mais complexo |
| Alpine base | 70-90% | Menos ferramentas de debug |
| Remover dev deps | 30-50% | Perda de headers, libs |
| Compress layers | 10-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-III | Atendimento |
|---|---|
| 6.1 | Containers imutáveis, verificados e versionados |
| 6.2 | Scanning obrigatório antes de deploy |
| 6.3 | Auditoria 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
| Risco | Consequência | Mitigação |
|---|---|---|
| Imagem não verificada em produção | Malware ou vulnerabilidade não detectada | Scan obrigatório antes de push |
| Secrets em Dockerfile ou imagem | Exposição de credencial | Usar secrets do Kubernetes, nunca em imagem |
| Base desatualizada | Vulnerabilidades conhecidas no SO | Atualizar base regularmente, rescan |
| Tag latest ao vivo | Imprevisibilidade de qual versão está rodando | Usar tags semânticas, latest apenas para staging |
| Layer não cacheável | Rebuild lento em CI/CD | Ordenar instruções para cachear máximo |
| Imagem gigante | Pull lento, custo de storage | Multi-stage, Alpine, remover build deps |
39.17 Decisões Arquiteturais
| ADR | Tema |
|---|---|
| ADR-601 | Docker como padrão de container |
| ADR-602 | Harbor como registry privado |
| ADR-603 | Trivy para scanning de vulnerabilidades |
| ADR-604 | Multi-stage build obrigatório |
| ADR-605 | Usuário não-root em todos os containers |
| ADR-606 | Versionamento semântico de imagens |
| ADR-607 | Replicação de imagens entre datacenters |
| ADR-608 | Assinatura 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
| Campo | Valor |
|---|---|
| Documento | Documento Mestre — Plataforma de Relacionamento Digital com o Cidadão |
| Capítulo | 39 — Containers e Empacotamento |
| Versão | 1.0 |
| Situação | Concluído |
| Última atualização | 16/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.
Capítulo 38 — Kubernetes e Orquestração de Containers
Este capítulo aprofunda a operação do Kubernetes como plataforma de orquestração da Plataforma de Relacionamento Digital com o Cidadão. Detalha como workloads são empacotados em containers, declarados em manifests, distr…
Capítulo 40 — DevSecOps e Entrega Contínua
Este capítulo detalha a estratégia de DevSecOps e Entrega Contínua (CI/CD) da Plataforma de Relacionamento Digital com o Cidadão, descrevendo como código, infraestrutura e testes fluem de forma automatizada, segura e con…