Infraestrutura como Código: Do Docker ao Terraform em Pipelines CI/CD

Infraestrutura como Código: Do Docker ao Terraform em Pipelines CI/CD
Introdução
A transformação digital das empresas depende cada vez mais da capacidade de entregar software rapidamente, com qualidade e segurança. Nesse cenário, a prática de Infraestrutura como Código (IaC) tornou‑se a espinha dorsal das organizações que buscam automação, reproducibilidade e governança.
Ao combinar Docker, Kubernetes, Terraform e GitHub Actions, é possível criar pipelines de CI/CD que:
Provisionam a infraestrutura de forma declarativa; Empacotam aplicações em containers consistentes; Orquestram serviços em clusters escaláveis; Entregam mudanças automaticamente em ambientes de teste e produção.
Este artigo apresenta, passo a passo, como montar essa cadeia completa, com exemplos reais de código, boas práticas e dicas de segurança. Ao final, você será capaz de reproduzir todo o fluxo em seu próprio projeto.
1. Containerização com Docker e Docker Compose
Por que Docker?
Isolamento: Cada serviço roda em seu próprio container, eliminando conflitos de dependência. Portabilidade: A mesma imagem funciona em laptops, servidores on‑premise ou nuvem. Velocidade: Builds incrementais reduzem o tempo de feedback nos testes.
Dockerfile básico
# Dockerfile
FROM python:3.11-slim
Variáveis de ambiente
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
Instala dependências do sistema
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential gcc && \
rm -rf /var/lib/apt/lists/
Diretório de trabalho
WORKDIR /app
Copia requisitos e instala
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
Copia código da aplicação
COPY . .
Porta que a aplicação escuta
EXPOSE 8000
Comando padrão
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Dica: Use a flag
--no-cache-dirpara evitar camadas desnecessárias e reduzir o tamanho da imagem.
Docker Compose para ambiente de desenvolvimento
# docker-compose.yml
version: "3.9"
services:
api:
build: .
ports:
- "8000:8000"
volumes:
- .:/app
environment:
- ENV=development
depends_on:
- db
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: devuser
POSTGRES_PASSWORD: devpass
POSTGRES_DB: devdb
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
pgdata:
Com docker compose up --build, você tem a API FastAPI e o PostgreSQL rodando localmente, prontos para testes automatizados.
2. Orquestração com Kubernetes e Helm
Quando a aplicação precisa escalar ou ser executada em múltiplas zonas, o Kubernetes entra em cena. Ele gerencia containers em um cluster, provendo balanceamento, auto‑recuperação e atualizações sem downtime.
Manifesto de Deployment
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
labels:
app: api
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: ghcr.io/empresa/api:latest
ports:
- containerPort: 8000
env:
- name: ENV
value: "production"
resources:
limits:
cpu: "500m"
memory: "256Mi"
requests:
cpu: "250m"
memory: "128Mi"
Service para exposição
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
type: LoadBalancer
selector:
app: api
ports:
- protocol: TCP
port: 80
targetPort: 8000
Helm Chart simplificado
Criar um Helm chart permite versionar a configuração do Kubernetes junto com o código da aplicação.
helm create api-chart
Estrutura resumida (api-chart/values.yaml):
replicaCount: 3
image:
repository: ghcr.io/empresa/api
pullPolicy: IfNotPresent
tag: "latest"
service:
type: LoadBalancer
port: 80
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 250m
memory: 128Mi
Instalação:
helm upgrade --install api-release ./api-chart --namespace production
Prática recomendada: Mantenha o
values.yamlfora do repositório (por exemplo, em um secret manager) e injete valores sensíveis via CI/CD.
3. Provisionamento Declarativo com Terraform
O Terraform permite descrever a infraestrutura (clusters, redes, bancos de dados) em arquivos .tf, garantindo que o estado seja versionado e auditável.
Provider e backend
# terraform/provider.tf
terraform {
required_version = ">= 1.5.0"
backend "s3" {
bucket = "tf-state-empresa"
key = "infra/prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
}
}
provider "google" {
project = var.project_id
region = var.region
}
Variáveis
# terraform/variables.tf
variable "project_id" {
description = "ID do projeto GCP"
type = string
}
variable "region" {
description = "Região onde os recursos serão criados"
type = string
default = "us-east1"
}
Cluster GKE
# terraform/gke.tf
resource "google_container_cluster" "primary" {
name = "prod-gke-cluster"
location = var.region
initial_node_count = 3
node_config {
machine_type = "e2-medium"
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform",
]
labels = {
environment = "production"
}
}
remove_default_node_pool = true
lifecycle {
prevent_destroy = true
}
}
Saída de credenciais para o pipeline
# terraform/outputs.tf
output "kubeconfig" {
description = "Kubeconfig para acesso ao cluster"
value = google_container_cluster.primary.endpoint
sensitive = true
}
Fluxo típico:
terraform init
terraform plan -var="project_id=empresa-prod" -out=plan.out
terraform apply "plan.out"
Os arquivos gerados (plan.out) podem ser consumidos por um job do GitHub Actions para atualizar o cluster automaticamente.
4. CI/CD Automatizado com GitHub Actions
O GitHub Actions oferece pipelines como código, permitindo que o fluxo de build, test e deploy seja armazenado no mesmo repositório da aplicação.
Workflow completo
```yaml
.github/workflows/ci-cd.yml
name: CI/CD Pipeline
on: push: branches: - main pull_request: branches: - main
env: REGISTRY: ghcr.io/empresa IMAGE_NAME: api TF_VERSION: 1.6.0
jobs: build-test: runs-on: ubuntu-latest steps: - name: Checkout código uses: actions/checkout@v4
- name: Configurar Python uses: actions/setup-python@v5 with: python-version: "3.11"
- name: Instalar dependências run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install pytest
- name: Executar testes unitários run: pytest -q
- name: Build da imagem Docker uses: docker/build-push-action@v5 with: context: . push: false tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
deploy: needs: build-test runs-on: ubuntu-latest environment: production permissions: contents: read id-token: write steps: - name: Checkout código uses: actions/checkout@v4
- name: Configurar Terraform uses: hashicorp/setup-terraform@v2 with: terraform_version: ${{ env.TF_VERSION }}
- name: Autenticar no GCP uses: google-github-actions/auth@v2 with: credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Inicializar Terraform run: terraform init -backend-config


