Files
adaptador-planilhas/docker-compose.yml
T
camilafagundesandClaude Opus 5 dea510c3b4 Imagem Docker e compose reproduzíveis para homologação
Não existia nenhum artefato de deploy: sem Dockerfile, sem compose, sem pin de
Node. O runbook pedia `npm run start` e `npm run worker` à mão, o que não é um
ambiente reproduzível, e o worker dependia de `tsx`, uma devDependency, que
`npm ci --omit=dev` removeria.

- Dockerfile multistage. Web e worker saem da mesma imagem: mesmo código,
  mesmas dependências, só o subcomando difere.
- `tsx` foi para `dependencies`. Conferido em diretório limpo: os 13 pacotes
  externos que src e scripts usam existem no install de produção.
- A sobreposição das duas árvores de node_modules é segura e foi medida: 318
  pacotes em produção contra 153 traçados, zero divergência de versão entre os
  compartilhados, e 3 que existem só na traçada, que o COPY mescla sem
  remover. O package.json do standalone não é sobrescrito.
- Entrypoint com subcomandos, que garante `node --import tsx` em todos os
  scripts. Usar `node` direto convidaria de volta o defeito do SIGTERM.
- Healthcheck de liveness na web e de heartbeat no worker.
- Compose local reproduz a topologia com Postgres e Redis de verdade. Compose
  de homologação não declara Postgres (é o banco gerenciado), usa Redis
  isolado com senha e volume próprios, publica porta só em 127.0.0.1 e tem
  nome de projeto, rede e volume exclusivos. Nenhum serviço de outro
  aplicativo do ecossistema é declarado, tocado ou reiniciado.
- `.env.staging.example` sem segredo, `.nvmrc`, `engines` e `packageManager`.
- `config/staging-seed.json` e `.env.staging` no gitignore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-15 20:39:29 -03:00

112 lines
3.1 KiB
YAML

# Reprodução local da topologia de homologação: mesma imagem, dois processos,
# Postgres e Redis de verdade. Serve para validar o artefato antes de subir ao
# servidor. Aqui o ambiente é `development`: não há Supabase local, então o
# armazenamento é um volume privado e a sessão usa o login local sem senha.
#
# docker compose up --build
# docker compose exec web /app/docker/entrypoint.sh migrate
#
# Nenhuma porta de serviço do ecossistema é usada: tudo em 127.0.0.1 e em
# portas altas, com nomes próprios de projeto, rede e volume.
name: adaptador-planilhas-local
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: adaptador
POSTGRES_PASSWORD: adaptador_local
POSTGRES_DB: adaptador
ports:
- "127.0.0.1:55432:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U adaptador -d adaptador"]
interval: 5s
timeout: 3s
retries: 20
networks: [adaptador]
redis:
image: redis:7-alpine
command: ["redis-server", "--save", "", "--appendonly", "no"]
ports:
- "127.0.0.1:56379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 20
networks: [adaptador]
web:
# Com ADAPTER_IMAGE definido, usa a imagem já construída (o CI faz isso).
# Sem ela, `up --build` constrói e marca com este nome.
image: ${ADAPTER_IMAGE:-adaptador-planilhas:local}
build:
context: .
target: runner
command: ["web"]
environment: &app-env
ADAPTER_ENV: development
ADAPTER_NAMESPACE: adaptador-planilhas
ADAPTER_JOB_MODE: worker
ADAPTER_APPLY_IDENTITY_SHIM: "1"
ADAPTER_DEV_AUTH: "1"
ADAPTER_DEV_AUTH_SECRET: segredo-apenas-local
DATABASE_URL: postgres://adaptador:adaptador_local@postgres:5432/adaptador
REDIS_URL: redis://redis:6379
SPREADSHEET_TEMP_TTL_SECONDS: "3600"
ELO_PRO_APP_URL: http://localhost:3000
PORT: "3000"
HOSTNAME: 0.0.0.0
ports:
- "127.0.0.1:3000:3000"
volumes:
- app-storage:/app/.data
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks: [adaptador]
worker:
image: ${ADAPTER_IMAGE:-adaptador-planilhas:local}
build:
context: .
target: runner
command: ["worker"]
environment: *app-env
volumes:
- app-storage:/app/.data
# O worker grava heartbeat ao fim de cada tick; o healthcheck detecta
# processo vivo mas travado, que um check de PID não pega.
healthcheck:
test: ["CMD", "/app/docker/entrypoint.sh", "worker-health"]
interval: 30s
timeout: 5s
start_period: 15s
retries: 3
stop_grace_period: 30s
depends_on:
web:
condition: service_started
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks: [adaptador]
networks:
adaptador:
name: adaptador-planilhas-local
volumes:
postgres-data:
name: adaptador-planilhas-local-postgres
app-storage:
name: adaptador-planilhas-local-storage