Como Usar Docker e Kubernetes em Produção Já leu

Docker em Produção: Containerização Eficiente 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. Para começar, você precisa criar um bem estruturado. Aqui está um exemplo prático com uma aplicação Node.js: Use como imagem base — é 50x menor que versões padrão, reduzindo superfície de ataque e tempo de deploy. Sempre use ao invés de em produção para garantir versões exatas. O é crucial: Kubernetes usa isso para monitorar a saúde do seu container. Multi-stage Builds para Otimização Imagens grandes causam pulls lentos e aumentam latência de deploys. Use multi-stage builds para separar ambiente de build do runtime: 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. Kubernetes

Docker em Produção: Containerização Eficiente

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.

Para começar, você precisa criar um Dockerfile bem estruturado. Aqui está um exemplo prático com uma aplicação Node.js:

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"]

Use alpine como imagem base — é 50x menor que versões padrão, reduzindo superfície de ataque e tempo de deploy. Sempre use npm ci ao invés de npm install em produção para garantir versões exatas. O HEALTHCHECK é crucial: Kubernetes usa isso para monitorar a saúde do seu container.

Multi-stage Builds para Otimização

Imagens grandes causam pulls lentos e aumentam latência de deploys. Use multi-stage builds para separar ambiente de build do runtime:

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"]

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.

Kubernetes em Produção: Orquestração em Escala

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 estado desejado e K8s trabalha para mantê-lo.

Um manifesto Kubernetes básico (arquivo YAML) define como sua aplicação deve rodar:

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

Este Deployment garante 3 réplicas sempre rodando. Se uma falhar, K8s cria outra automaticamente. Os resources 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.

Exposição de Serviços e Load Balancing

Um Deployment precisa de um Service para ser acessível. O Service funciona como um load balancer interno:

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

Para HTTPS em produção, use um Ingress com controlador Nginx:

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

Gerenciamento de Configuração e Secrets

Nunca hardcode credenciais. Use ConfigMaps para configurações e Secrets para dados sensíveis:

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!

Boas Práticas para Produção

1. Versionamento de Imagens: Nunca use latest em produção. Use tags semânticas (v1.2.0) e atualize manifestos Kubernetes explicitamente. Isso torna rollbacks triviais — basta mudar a tag na imagem.

2. Resource Quotas e Limits: Configure limits não apenas em containers individuais, mas em namespaces inteiros. Previne uma aplicação malformada de consumir todos os recursos do cluster:

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"

3. Monitoramento Ativo: Configure prometheus + alertmanager. Um Deployment sem observabilidade é como pilotar no escuro. Configure alertas para CPU >80%, memória >85% e taxa de erro >1%.

4. GitOps: 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.

Conclusão

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.

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.

Referências


Artigos relacionados