DevOps Guidelines
PadrΓ΅es de infraestrutura e deployment para projetos InfoWhere
EstratΓ©gia de Ambientes
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LOCAL (desenvolvimento) β
β β
β β’ Docker + Docker Compose β
β β’ Portainer (opcional, para visualizar) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β PRODUΓΓO (sempre) β
β β
β β’ Kubernetes + Helm β
β β’ ArgoCD (GitOps, CD) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Estrutura de Arquivos
{projeto}/
βββ docker-compose.yml # Local: desenvolvimento
βββ docker-compose.override.yml # Local: overrides (volumes, debug)
βββ Dockerfile # Build da imagem
βββ helm/ # ProduΓ§Γ£o: K8s
β βββ {projeto}/
β βββ Chart.yaml
β βββ values.yaml
β βββ values-staging.yaml
β βββ values-prod.yaml
β βββ templates/
β βββ deployment.yaml
β βββ service.yaml
β βββ ingress.yaml
β βββ configmap.yaml
β βββ secrets.yaml
βββ .github/
βββ workflows/
βββ ci-cd.yml # Build β Push β ArgoCD sync
Docker
Regras
- Sempre usar imagens base mΓnimas e seguras (ex:
alpine,distroless) - Preferir multi-stage builds para reduzir tamanho da imagem
- NΓ£o hardcodar secrets ou credenciais em Dockerfiles
- Sempre fixar versΓ΅es das imagens base (nada de
latest) - Imagens devem permanecer leves (remover tools/packages nΓ£o utilizados)
Exemplo Dockerfile (Java)
# Build stage
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN ./mvnw package -DskipTests
# Runtime stage
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Exemplo Dockerfile (Python)
# Build stage
FROM python:3.12-slim AS builder
WORKDIR /app
RUN pip install uv
COPY pyproject.toml .
RUN uv pip install --system -r pyproject.toml
# Runtime stage
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Docker Compose (Local)
Regras
- Usar arquivos
.envpara configuraΓ§Γ£o β nunca hardcodar credenciais - NΓ£o expor portas desnecessΓ‘rias
- Services devem ter nomes claros (ex:
app,db,redis) - Usar healthchecks para services crΓticos
Exemplo
# docker-compose.yml
services:
app:
build: .
ports:
- "8080:8080"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- KEYCLOAK_URL=http://keycloak:8080
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
# docker-compose.override.yml (local dev)
services:
app:
volumes:
- ./src:/app/src
environment:
- DEBUG=true
Kubernetes
Regras
- Sempre definir
apiVersionexplicitamente - Definir resources.limits e resources.requests para containers
- NΓ£o hardcodar secrets nos manifests β usar Secrets/ConfigMaps
- Preferir
Deployment+Serviceem vez de Pods raw - Ingress deve usar host-based routing
- Sempre definir liveness e readiness probes
Exemplo Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myregistry/myapp:1.0.0
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
envFrom:
- configMapRef:
name: myapp-config
- secretRef:
name: myapp-secrets
Helm
Regras
- Usar values.yaml para configuraΓ§Γ£o β nada de hardcoding nos templates
- VersΓ΅es do Chart devem ser incrementadas a cada mudanΓ§a
- Evitar duplicaΓ§Γ£o β reutilizar helpers/templates
- Sempre validar com
helm lint
Estrutura
helm/{projeto}/
βββ Chart.yaml # Metadata do chart
βββ values.yaml # Valores padrΓ£o
βββ values-staging.yaml # Override staging
βββ values-prod.yaml # Override produΓ§Γ£o
βββ templates/
βββ _helpers.tpl # FunΓ§Γ΅es auxiliares
βββ deployment.yaml
βββ service.yaml
βββ ingress.yaml
βββ configmap.yaml
βββ secrets.yaml
Exemplo values.yaml
replicaCount: 2
image:
repository: myregistry/myapp
tag: "1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8080
ingress:
enabled: true
host: myapp.example.com
tls: true
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
env:
DATABASE_URL: "" # Definido via secrets
ArgoCD (GitOps)
Fluxo
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ
β Git βββββΆβ Build βββββΆβ Push βββββΆβ ArgoCD β
β Push β β Image β β Registryβ β Sync β
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ
β β
βΌ βΌ
Docker Hub Kubernetes
(ou outro) Cluster
Exemplo Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/infowhere/myapp.git
targetRevision: main
path: helm/myapp
helm:
valueFiles:
- values.yaml
- values-prod.yaml
destination:
server: https://kubernetes.default.svc
namespace: myapp
syncPolicy:
automated:
prune: true
selfHeal: true
CI/CD
Regras
- Pipelines devem incluir: build β test β lint β security scan β deploy
- Nenhum deploy sem passar todos os testes
- Usar cache de dependΓͺncias para acelerar builds
- NΓ£o armazenar secrets nas configs de pipeline β usar vaults/secret stores
- Todos os artefatos (Docker images, Helm charts, JARs) devem ser versionados e imutΓ‘veis
Exemplo GitHub Actions
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Build & Test
run: ./mvnw verify
- name: SonarQube Scan
run: ./mvnw sonar:sonar
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: Build Docker Image
run: docker build -t myregistry/myapp:${{ github.sha }} .
- name: Push to Registry
if: github.ref == 'refs/heads/main'
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker push myregistry/myapp:${{ github.sha }}
- name: Update Helm values
if: github.ref == 'refs/heads/main'
run: |
sed -i "s/tag: .*/tag: ${{ github.sha }}/" helm/myapp/values-prod.yaml
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git commit -am "chore: update image tag to ${{ github.sha }}"
git push
Resumo
| Ambiente | OrquestraΓ§Γ£o | CD | VisualizaΓ§Γ£o |
|---|---|---|---|
| Local | Docker Compose | - | Portainer (opcional) |
| ProduΓ§Γ£o | K8s + Helm | ArgoCD | ArgoCD UI |