<h2>Docker em Produção: Containerização Eficiente</h2>
<p>Docker é essencial para qualquer infraestrutura moderna. Um container Docker encapsula sua aplicação com todas as dependências, garantindo que funcione identicamente em desenvolvimento, teste e produção. A vantagem crítica é eliminar o famoso "funciona na minha máquina" — você entrega um artefato testado e imutável.</p>
<p>Para começar, você precisa criar um <code>Dockerfile</code> bem estruturado. Aqui está um exemplo prático com uma aplicação Node.js:</p>
<pre><code class="language-dockerfile">FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node healthcheck.js
CMD ["node", "server.js"]</code></pre>
<p>Use <code>alpine</code> como imagem base — é 50x menor que versões padrão, reduzindo superfície de ataque e tempo de deploy. Sempre use <code>npm ci</code> ao invés de <code>npm install</code> em produção para garantir versões exatas. O <code>HEALTHCHECK</code> é crucial: Kubernetes usa isso para monitorar a saúde do seu container.</p>
<h3>Multi-stage Builds para Otimização</h3>
<p>Imagens grandes causam pulls lentos e aumentam latência de deploys. Use multi-stage builds para separar ambiente de build do runtime:</p>
<pre><code class="language-dockerfile">FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
EXPOSE 3000
CMD ["node", "dist/index.js"]</code></pre>
<p>Isso reduz drasticamente o tamanho final — você descarta ferramentas de build que não são necessárias em runtime. A imagem final contém apenas o essencial.</p>
<h2>Kubernetes em Produção: Orquestração em Escala</h2>
<p>Kubernetes (K8s) gerencia containers automaticamente em clusters. Enquanto Docker é sobre criar e empacotar, Kubernetes é sobre orquestrar centenas de containers, gerenciar recursos, escalar e recuperar falhas. Você define o <em>estado desejado</em> e K8s trabalha para mantê-lo.</p>
<p>Um manifesto Kubernetes básico (arquivo YAML) define como sua aplicação deve rodar:</p>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api-server
template:
metadata:
labels:
app: api-server
spec:
containers:
- name: api-server
image: seu-registry.com/api-server:1.2.0
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
- name: DB_HOST
valueFrom:
secretKeyRef:
name: db-credentials
key: host
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 10</code></pre>
<p>Este Deployment garante 3 réplicas sempre rodando. Se uma falhar, K8s cria outra automaticamente. Os <code>resources</code> definem quanto CPU e memória cada pod pode usar — essencial para evitar que uma aplicação mate outras no cluster. Os probes (liveness e readiness) informam ao K8s quando remover um pod do tráfego.</p>
<h3>Exposição de Serviços e Load Balancing</h3>
<p>Um Deployment precisa de um Service para ser acessível. O Service funciona como um load balancer interno:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Service
metadata:
name: api-server-service
namespace: production
spec:
type: LoadBalancer
selector:
app: api-server
ports:
- protocol: TCP
port: 80
targetPort: 3000</code></pre>
<p>Para HTTPS em produção, use um Ingress com controlador Nginx:</p>
<pre><code class="language-yaml">apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.seu-dominio.com
secretName: api-tls-cert
rules:
- host: api.seu-dominio.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-server-service
port:
number: 80</code></pre>
<h3>Gerenciamento de Configuração e Secrets</h3>
<p>Nunca hardcode credenciais. Use ConfigMaps para configurações e Secrets para dados sensíveis:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
LOG_LEVEL: "info"
CACHE_TTL: "3600"
---
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: production
type: Opaque
stringData:
host: postgres.internal
user: appuser
password: senhaForte123!</code></pre>
<h2>Boas Práticas para Produção</h2>
<p><strong>1. Versionamento de Imagens:</strong> Nunca use <code>latest</code> em produção. Use tags semânticas (<code>v1.2.0</code>) e atualize manifestos Kubernetes explicitamente. Isso torna rollbacks triviais — basta mudar a tag na imagem.</p>
<p><strong>2. Resource Quotas e Limits:</strong> Configure limits não apenas em containers individuais, mas em namespaces inteiros. Previne uma aplicação malformada de consumir todos os recursos do cluster:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Namespace
metadata:
name: production
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.cpu: "50"
requests.memory: "100Gi"
limits.cpu: "100"
limits.memory: "200Gi"</code></pre>
<p><strong>3. Monitoramento Ativo:</strong> Configure prometheus + alertmanager. Um Deployment sem observabilidade é como pilotar no escuro. Configure alertas para CPU >80%, memória >85% e taxa de erro >1%.</p>
<p><strong>4. GitOps:</strong> Mantenha todo manifesto Kubernetes em git. Use ferramentas como ArgoCD para sincronizar automaticamente o estado do cluster com o repositório. Isso torna mudanças rastreáveis e revertíveis.</p>
<h2>Conclusão</h2>
<p>Docker containeriza suas aplicações de forma reproduzível; Kubernetes as orquestra em escala. Na prática: (1) construa imagens Docker otimizadas com multi-stage builds e use secrets/configs separados, (2) defina Deployments, Services e Ingress em YAML descritivo, deixando K8s resolver scheduling e recuperação de falhas, (3) implemente limits de recursos, health checks e monitore tudo — observabilidade não é luxo.</p>
<p>O caminho para dominar essa stack é iterativo: comece com um cluster local (minikube), progresse para managed services (EKS, GKE) e evolua sua arquitetura conforme a complexidade cresce.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://docs.docker.com/" target="_blank" rel="noopener noreferrer">Docker Official Documentation</a></li>
<li><a href="https://kubernetes.io/docs/" target="_blank" rel="noopener noreferrer">Kubernetes Official Documentation</a></li>
<li><a href="https://12factor.net/" target="_blank" rel="noopener noreferrer">12 Factor App Methodology</a></li>
<li><a href="https://www.manning.com/books/kubernetes-in-action" target="_blank" rel="noopener noreferrer">Kubernetes in Action by Marko Lukša</a></li>
<li><a href="https://snyk.io/blog/10-docker-image-security-best-practices/" target="_blank" rel="noopener noreferrer">Docker & Kubernetes Security Best Practices</a></li>
</ul>