Docker Compose: Orquestração de Serviços com Traefik e SSL

10 min de leitura Docker
Docker Compose: Orquestração de Serviços com Traefik e SSL

O que é Docker Compose e por que ele é essencial

No mundo da infraestrutura moderna e do desenvolvimento ágil, a capacidade de provisionar ambientes complexos com um único comando é um diferencial competitivo. O Docker Compose é a ferramenta oficial da Docker para definir e executar aplicações multi-contêiner. Enquanto o comando docker run é excelente para iniciar um único serviço isolado, ele se torna impraticável quando precisamos orquestrar uma arquitetura completa: frontend, backend, banco de dados, cache e proxy reverso.

O Docker Compose utiliza um arquivo em formato YAML (docker-compose.yml) para configurar os serviços da sua aplicação. Esse arquivo define as redes, volumes, variáveis de ambiente e dependências entre os containers. Ao executar o comando docker compose up, o motor do Docker lê essa configuração e cria todos os recursos necessários simultaneamente, garantindo que a orquestração ocorra na ordem correta.

Neste tutorial, vamos construir uma stack completa em um ambiente VPS Linux. Utilizaremos o Traefik como reverse proxy para gerenciar o roteamento de tráfego e obter certificados SSL automáticos via Let's Encrypt. Além disso, configuraremos volumes persistentes para garantir que seus dados não sejam perdidos quando os containers forem reiniciados ou atualizados.

Pré-requisitos e Preparação do Ambiente

Antes de mergulhar na configuração do Compose, certifique-se de que seu servidor VPS atenda aos seguintes requisitos:

  • Um sistema operacional Linux moderno (Ubuntu 22.04 LTS ou Debian 12 recomendados).
  • Docker Engine instalado e atualizado.
  • Docker Compose Plugin instalado (ou a versão standalone, dependendo da sua instalação).
  • Dois domínios apontando para o IP público do seu servidor (ex: app.seudominio.com e db.seudominio.com). Você pode usar subdomínios temporários para testes.

Para verificar se o Docker está funcionando corretamente, execute:

docker --version
docker compose version

Crie um diretório dedicado para este projeto. Isso manterá seu sistema organizado e facilitará o backup da configuração.

mkdir ~/docker-traefik-stack && cd ~/docker-traefik-stack

Estrutura de Arquivos do Projeto

A organização dos arquivos é crucial para a manutenibilidade. Vamos criar uma estrutura simples mas robusta:

  • docker-compose.yml: O arquivo principal de orquestração.
  • traefik/: Diretório para configurações específicas do Traefik.
  • app/: Diretório para a aplicação web (usaremos um container nginx simples como exemplo).
mkdir -p traefik app

Dentro da pasta app, crie um arquivo HTML simples para testar:

echo "<h1>Olá, Mundo Docker!</h1>" > app/index.html

Configurando o Traefik como Reverse Proxy

O Traefik é um reverse proxy moderno e dinâmico que se integra nativamente ao Docker. Ele lê as labels dos containers em tempo real para criar rotas automaticamente. Isso elimina a necessidade de reiniciar o servidor web sempre que adicionamos um novo serviço.

Criando o arquivo de configuração do Traefik

Crie o arquivo traefik/traefik.yml. Este arquivo define os endpoints de entrada, a integração com o Docker e as configurações de SSL.

global:
  checkNewVersion: true
  sendAnonymousUsage: false

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: web
  file:
    filename: /etc/traefik/dynamic.yml
    watch: true

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

certificatesResolvers:
  letsencrypt:
    acme:
      email: "[email protected]"
      storage: /etc/traefik/acme.json
      httpChallenge:
        entryPoint: web

Nota importante: Substitua [email protected] por um endereço de e-mail válido. Esse e-mail será usado para notificações de expiração de certificados e recuperação de chave.

Criando o arquivo Docker Compose principal

Agora, vamos definir os serviços no docker-compose.yml. Este arquivo orquestrará o Traefik e nossa aplicação de exemplo.

version: '3.8'

services:
  traefik:
    image: traefik:v2.10
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080" # Dashboard (recomendado restringir acesso)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
      - ./traefik/acme.json:/etc/traefik/acme.json
      - ./traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
    networks:
      - web

  app:
    image: nginx:alpine
    container_name: minha-app
    restart: unless-stopped
    volumes:
      - ./app:/usr/share/nginx/html:ro
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`app.seudominio.com`)"
      - "traefik.http.routers.app.entrypoints=websecure"
      - "traefik.http.routers.app.tls.certresolver=letsencrypt"
      - "traefik.http.services.app.loadbalancer.server.port=80"
    networks:
      - web

networks:
  web:
    external: true

Analisemos os pontos cruciais desta configuração:

  1. Volumes do Socket: A linha /var/run/docker.sock:/var/run/docker.sock:ro permite que o Traefik ouça eventos do Docker. O sufixo :ro garante acesso apenas leitura, melhorando a segurança.
  2. Redes Externas: Definimos a rede web como externa. Isso é uma boa prática para permitir que outros containers (como bancos de dados) se conectem à mesma rede sem precisar ser declarados neste arquivo específico, facilitando a expansão da stack.
  3. Labels do Traefik: Na seção app, as labels dizem ao Traefik: "Ative o proxy para este container", "Roteie tráfego para o domínio especificado", "Use TLS com Let's Encrypt" e "Encaminhe para a porta 80 interna do Nginx".

Volumes Persistentes e Isolamento de Dados

Um erro comum em ambientes Docker é perder dados quando um container é removido. Para aplicações reais, como bancos de dados ou sistemas de arquivos, isso é inaceitável. O Docker Compose resolve isso através de volumes nomeados.

No exemplo acima, usamos volumes de montagem de arquivo (./app:/usr/share/nginx/html:ro). Isso é ideal para código fonte ou configurações estáticas. No entanto, para dados dinâmicos, devemos usar volumes gerenciados pelo Docker.

Imagine que adicionamos um serviço de banco de dados PostgreSQL à nossa stack. A configuração seria:

  db:
    image: postgres:15-alpine
    container_name: postgres-db
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: senha_segura_aqui
      POSTGRES_DB: myapp
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - web

volumes:
  db-data:

A seção volumes no final do arquivo cria um volume persistente chamado db-data. Mesmo se o container postgres-db for destruído, os dados na pasta /var/lib/postgresql/data dentro do volume permanecerão intactos. Ao recriar o container com a mesma configuração, os dados serão restaurados automaticamente.

Dicas de Segurança para Volumes

  • Sempre defina permissões de leitura/escrita adequadas.
  • Nunca armazene senhas ou chaves de API diretamente no código-fonte do container; use variáveis de ambiente ou arquivos montados com restrições rígidas.
  • Faça backups regulares dos diretórios onde os volumes são armazenados fisicamente no host (geralmente em /var/lib/docker/volumes/).

Orquestração Avançada: Dependências e Healthchecks

A orquestração eficiente não depende apenas de iniciar containers na ordem correta, mas também de garantir que eles estejam prontos para receber tráfego. O Docker Compose suporta depends_on, mas ele espera apenas pelo início do container, não pela inicialização completa do serviço (ex: banco de dados aceitando conexões).

Para uma orquestração robusta, utilizamos Healthchecks. Vamos atualizar a configuração do banco de dados para incluir um verificador de saúde:

  db:
    image: postgres:15-alpine
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

Agora, atualizamos o serviço da aplicação para depender da saúde do banco de dados:

  app:
    depends_on:
      db:
        condition: service_healthy

Essa configuração garante que a aplicação app só será iniciada após o PostgreSQL estar realmente pronto para aceitar conexões, prevenindo erros de conexão nas primeiras tentativas do sistema.

Troubleshooting Containers Docker

Mesmo com configurações perfeitas, erros podem ocorrer. O Docker Compose oferece comandos poderosos para diagnóstico. Aqui estão os cenários mais comuns e como resolvê-los.

1. Logs Centralizados

Ao invés de acessar cada container individualmente, o Compose permite ver todos os logs em um único fluxo:

docker compose logs -f --tail=50

O flag -f mantém o terminal aberto para novos logs em tempo real. O --tail=50 mostra apenas as últimas 50 linhas, útil se os logs forem muito antigos.

2. Verificando o Status dos Serviços

Para ver rapidamente quais containers estão rodando, parados ou com falha:

docker compose ps

Se um serviço estiver em estado Exited, verifique os logs específicos dele:

docker compose logs app

3. Problemas com SSL e Traefik

Se o certificado Let's Encrypt não for obtido, verifique os seguintes pontos:

  • O domínio está corretamente apontando para o IP do servidor (verifique com nslookup seu-domínio.com)?
  • As portas 80 e 443 estão abertas no firewall do VPS? Use ufw status ou firewall-cmd --list-all.
  • O arquivo acme.json tem permissões de leitura para o usuário do container? Se necessário, ajuste com chmod 600 ./traefik/acme.json.

4. Containers "Zumbis"

Às vezes, containers param mas não são removidos. Para limpar todo o ambiente:

docker compose down -v

O flag -v remove também os volumes nomeados definidos no arquivo. Use com cautela, pois isso apaga dados persistentes.

Boas Práticas para Produção

Ao levar sua stack Docker Compose para produção em um VPS, considere as seguintes práticas:

  1. Imagens Estáveis: Evite usar tags latest em produção. Especifique versões exatas, como nginx:1.25-alpine, para garantir reprodutibilidade.
  2. Segurança de Rede: Não exponha portas internas (como a do banco de dados) diretamente ao mundo exterior. Deixe que apenas o Traefik ou serviços específicos exponham portas na porta 80/443.
  3. Monitoramento: Integre ferramentas como Prometheus e Grafana em sua stack para monitorar métricas de desempenho e disponibilidade.
  4. Backup Automático: Implemente scripts cron ou ferramentas como restic ou kopia para backup automático dos volumes de dados.

Conclusão

O Docker Compose transforma a complexidade da orquestração de múltiplos serviços em uma tarefa gerenciável e repetível. Ao combinar o poder do Docker com a inteligência do Traefik, você cria uma infraestrutura resiliente, segura e escalável. A configuração de volumes persistentes garante a integridade dos seus dados, enquanto os healthchecks asseguram a estabilidade da aplicação.

A partir deste tutorial, você tem as bases para implantar aplicações profissionais em sua VPS. Lembre-se: a chave para o sucesso com containers é a documentação clara das dependências e o monitoramento contínuo. Experimente adicionar novos serviços à sua stack, como Redis para cache ou Elasticsearch para busca, utilizando os mesmos princípios de rede e volumes apresentados aqui.

A infraestrutura como código não é apenas uma tendência; é o padrão atual para desenvolvimento e operações de TI. Domine o Docker Compose e você estará preparado para qualquer desafio de orquestração moderna.

Compartilhar: Link copiado!
Esse tutorial foi útil?

Comentários (0)

Seja o primeiro a comentar.

Deixe seu comentário

Seu comentário será analisado antes de ser publicado.

0/2000