Docker
Use multi-stage builds. Imagens menores = deploy mais rápido + menos superfície de ataque.
Não rode como root. Crie um usuário no Dockerfile:
RUN adduser -D appuser
USER appuserUse .dockerignore. Não copie .git, node_modules, .env para a imagem.
Tagueie imagens com versões específicas, nunca confie em latest em produção:
# Ruim
docker pull nginx
# Bom
docker pull nginx:1.25.3-alpineAproveite o cache. Coloque o que muda menos no topo do Dockerfile.
Um processo por container. Container não é VM. Rode um serviço por container.
Logue em stdout/stderr, não em arquivo. O orquestrador captura.
Trate sinais. Faça graceful shutdown ao receber SIGTERM. Em Go:
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigs
server.Shutdown(ctx)
}()Kubernetes
Sempre defina requests e limits. Sem isso, um pod pode consumir todo o recurso do node.
Use liveness e readiness probes:
- Liveness: "tá vivo?" — se falhar, K8s reinicia o pod.
- Readiness: "tá pronto pra receber tráfego?" — se falhar, K8s tira do balanceamento.
Use namespaces para separar ambientes ou times.
Não armazene segredos no Git. Use Secrets, ferramentas como Sealed Secrets, Vault, External Secrets.
Versione seus manifests. Trate eles como código (GitOps com ArgoCD/Flux).
Use labels consistentes: app, version, environment. Facilita queries e organização.
Pelo menos 2 réplicas para serviços importantes. 1 réplica = ponto único de falha.
Configure PodDisruptionBudgets para garantir disponibilidade durante manutenções.
Não use :latest em manifests. Versão exata torna deploys reproduzíveis.
Linux / Geral
Aprenda a ler logs. journalctl, tail -f, kubectl logs. 80% dos problemas se resolvem lendo log.
Use ferramentas de observabilidade. Prometheus + Grafana, ELK, Loki.
Automatize tudo. Se você fez algo manualmente duas vezes, deveria estar num script.
Faça backup do etcd. É o coração do cluster.