CI e CD: imutabilidade vs configuração de ambiente | Devops
- CI e CD: imutabilidade vs configuração de ambiente | Devops
Ideia central (a mais importante)
A separação correta entre CI e CD é:
CI produz um artefato imutável CD aplica os detalhes de ambiente para executar esse artefato
Se você internalizar isso, evita 90% dos erros de pipeline.
O que significa “imutável” na prática
Imutável = o artefato:
- não muda entre ambientes
- não é recompilado
- não recebe ajustes internos
- é exatamente o mesmo byte a byte
Exemplos de artefato:
- imagem Docker
- binário
.dll - pacote
.zip - release versionado
Papel do CI
O CI é responsável por gerar um pacote fechado, testado e imutável.
A missão do CI é:
“Gerar algo confiável que nunca mais precisa ser alterado”
O que entra no CI
Validação
- restore
- build
- testes
- lint
- análise estática
- validações de segurança
Empacotamento
- build final
- criação de imagem Docker
- versionamento
- push para registry
Resultado do CI
Um artefato único:
api:1.0.42
Esse artefato é:
- testado
- confiável
- imutável
O que NÃO entra no CI
O CI não deve:
- conhecer ambiente (dev, prod, etc)
- ter senha de banco
- ter URL de serviço externo
- fazer deploy em produção
- alterar comportamento por ambiente
Se o CI muda o artefato por ambiente, você perdeu imutabilidade.
Papel do CD
O CD pega o artefato imutável e injeta contexto de execução.
A missão do CD é:
“Fazer o mesmo artefato funcionar em ambientes diferentes”
O que entra no CD
Configuração de ambiente
- variáveis de ambiente
- secrets
- endpoints
- feature flags
- configurações específicas
Deploy
- docker compose / swarm / k8s
- ssh / release pipeline
- rollout
Validação
- health check
- readiness
- smoke test
Exemplo direto (Docker)
CI gera
docker build -t api:1.0.42 .
docker push registry/api:1.0.42
👉 acabou o CI
CD aplica contexto
docker run \
-e DB_CONNECTION=prod-db \
-e JWT_KEY=xxxx \
-e OTLP_ENDPOINT=https://otel \
api:1.0.42
👉 mesmo artefato, comportamentos diferentes
Separação correta (visual)
CI
└── build + test + package
└── artefato imutável (api:1.0.42)
CD
└── pega artefato
├── injeta variáveis
├── aplica secrets
├── escolhe ambiente
└── faz deploy
O erro clássico
❌ Build no CD
docker build ...
👉 errado
Você está criando outro artefato
❌ Variáveis dentro do build
ENV DB_CONNECTION=prod
👉 errado
Você está acoplando ambiente ao artefato
❌ Arquivo .env versionado no CI
👉 errado para produção
Forma correta
CI
build:
- dotnet build
- dotnet test
- docker build
- docker push
CD
deploy:
- pull da imagem
- gerar .env dinamico
- docker compose up -d
Regra de ouro
Build uma vez. Rode em qualquer lugar.
Se você precisa rebuildar para outro ambiente, o design está errado.
Variáveis e secrets
CI usa
- token de acesso ao registry
- chave de build
- dependências privadas
CD usa
- senha de banco
- JWT secret
- endpoint OTLP
- config de infra
Aplicando no seu cenário
Você já trabalha com:
- Docker
- API .NET
- pipeline
- envs
Então o desenho correto é:
CI
- gera imagem Docker
- publica no registry
- não conhece produção
CD
- conecta via SSH
- cria
.env - injeta secrets
- sobe container
Benefícios reais dessa separação
✔️ Segurança
Secrets nunca entram no build
✔️ Reprodutibilidade
Mesmo artefato em todos ambientes
✔️ Debug
Você sabe exatamente o que foi deployado
✔️ Rollback
Voltar versão é trivial
docker run api:1.0.41
Quando CI/CD estão errados
Sinais claros:
- “funciona em dev mas não em prod”
- rebuild por ambiente
- múltiplas imagens para o mesmo código
.envdentro do repositório de produção- comportamento diferente com mesmo commit
Modelo mental definitivo
CI
cria algo que não muda
CD
faz esse algo funcionar em qualquer contexto
Resumo final
| Responsabilidade | CI | CD |
|---|---|---|
| Build | ✔️ | ❌ |
| Testes | ✔️ | ❌ |
| Empacotamento | ✔️ | ❌ |
| Imutabilidade | ✔️ | ❌ |
| Variáveis de ambiente | ❌ | ✔️ |
| Secrets | ❌ | ✔️ |
| Deploy | ❌ | ✔️ |
| Configuração de ambiente | ❌ | ✔️ |
Frase para fixar
CI entrega um artefato imutável. CD adiciona contexto para ele rodar.