# Infraestrutura e Traefik Última atualização: 20/08/2026 ## Variantes de orquestração | Arquivo | Uso | |---|---| | `docker-compose.yml` | Fonte de verdade — dev local e produção (host único) | | `docker-compose.prod-test.yaml` | Bancada de teste de configuração antes de ir para produção | | `docker-compose.swarm.yaml` | Orquestração multi-nó (não usada atualmente) | Ver ADR 0001 (`docs/decisions/0001-docker-compose-vs-swarm.md`, também no site de Desenvolvimento → Decisões) para o raciocínio completo. ## Padrão de labels Traefik Todos os serviços HTTP seguem o modelo em `docs/modelo trafik yaml/docker-compose.yaml`: ```yaml labels: - 'traefik.enable=true' - 'traefik.http.routers.${PROJECT_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)' - 'traefik.http.routers.${PROJECT_NAME}.tls=true' - 'traefik.http.routers.${PROJECT_NAME}.entrypoints=websecure' - 'traefik.http.routers.${PROJECT_NAME}.tls.certresolver=lets-encrypt' - 'traefik.http.middlewares.${PROJECT_NAME}.headers.SSLRedirect=true' # ... demais headers de segurança (STS, XSS, nosniff) - 'traefik.http.routers.${PROJECT_NAME}.middlewares=${PROJECT_NAME}@docker' ``` Pontos importantes deste padrão: - **`certresolver` é `lets-encrypt`** (com hífen) — o nome do resolver configurado no Traefik do host. Um erro comum é usar `letsencrypt` (sem hífen), o que causa fallback silencioso para o certificado default self-signed do Traefik (ver [Divergências conhecidas](../troubleshooting/divergencias-conhecidas.md)). - Serviços que **não servem HTTP** (workers de fila) devem ter `traefik.enable=false` **explícito** — sem isso, o provider Docker do Traefik expõe o container por padrão (`exposedByDefault`), criando um router implícito `Host()` (ver [runbook de correção](../runbooks/correcao-exposicao-traefik.md)). - Healthchecks em imagens Alpine devem usar `wget` (não `curl`, ausente em várias imagens publicadas) e `127.0.0.1` explícito em vez de `localhost` (musl resolve `localhost` para `::1`/IPv6 antes de IPv4, e a maioria dos serviços só escuta em `0.0.0.0`). ## Roteamento da API (`evocrm-api.vya.digital`) O domínio da API é compartilhado entre `evo-auth`, `evo-crm`, `evo-core` e `evo-processor`, roteado por prioridade de `PathPrefix`/`PathRegexp` — rotas mais específicas (ex.: `/api/v1/accounts/:id`, webhooks com `accountId`) recebem prioridade maior que os catch-alls genéricos de cada serviço. O `evo-crm` tem o catch-all absoluto (`PathPrefix('/')`, prioridade 1). ## Rede Todos os serviços — incluindo os workers Sidekiq — devem estar na rede `app-network` (externa, pré-existente no host) para resolver hostnames internos como `redis.vyadigital`. Serviços fora dessa rede não conseguem resolver dependências internas mesmo estando "up".