Files
Reem-Notas/docker-compose.yml
victor 7fa2336b35 Corrige acesso em produção: hosts permitidos, i18n do Devise e config do ambiente no compose
- production.rb (hosts): a linha que parecia só liberar o APP_HOST na verdade
  LIGAVA a verificação de Host e recusava todo o resto — o acesso pelo IP
  interno caía em 'Blocked hosts: 100.75.222.23:3001'. Agora entram também
  localhost/127.0.0.1 e a lista HOSTS_PERMITIDOS.
- production.rb (i18n): 'fallbacks = true' significa cair no default_locale,
  que aqui é o próprio pt-BR — o fallback apontava para si mesmo e chave
  ausente virava 'Translation missing' na tela do usuário. Agora [:en], igual
  ao application.rb.
- pt-BR.yml: traduções do Devise (failure/sessions/passwords). O projeto não
  usa devise-i18n; em development o texto vinha em inglês pelo fallback e o
  buraco passava despercebido.
- docker-compose.yml / .env.example: porta do host parametrizada
  (${PORTA_APP:-3001}) e APP_HOST/APP_NAME/WHATSAPP_URL/HOSTS_PERMITIDOS com
  padrão — essa configuração vivia só no .env do servidor e sumiu junto com ele.
2026-08-27 18:30:17 -03:00

122 lines
5.7 KiB
YAML

version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
# PORTA DO HOST parametrizada — a do container é sempre 3000.
#
# POR QUE NÃO É FIXA: o mesmo NAS roda mais de um stack, e dois containers
# não publicam a mesma porta ("driver failed programming external
# connectivity ... port is already allocated"). O ambiente de TESTE usa a
# 3001; a 3000 já está ocupada. Por isso o PADRÃO aqui é 3001 e não 3000:
# é o valor que mantém ESTE ambiente de pé se o .env se perder — foi
# exatamente o que aconteceu, e o padrão 3000 fez o container morrer com
# "port is already allocated". Na produção (branch main) o padrão é 3000.
#
# Isto vivia como alteração LOCAL no docker-compose.yml do servidor — e em
# 27/08/2026 um `git reset --hard` levou junto, derrubando o ambiente com o
# proxy apontando para uma porta sem ninguém escutando. Parametrizado aqui,
# a porta passa a morar no .env (que o reset não toca) e o arquivo fica
# igual em todos os ambientes.
#
# ⚠️ Ao mudar, ajuste JUNTO o proxy reverso (DSM/Cloudflare) — senão o 502
# só muda de lugar.
ports:
- "${PORTA_APP:-3001}:3000"
env_file: .env
environment:
DATABASE_URL: ${DATABASE_URL}
DB_HOST: ${DB_HOST}
DB_PORT: ${DB_PORT}
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
RAILS_ENV: ${RAILS_ENV:-development}
# Fuso do SISTEMA OPERACIONAL dentro do container (o do Rails vem do
# config.time_zone). Já fixado no Dockerfile; repetido aqui para dar o
# ajuste sem rebuild — basta TZ=... no .env. Ver deploy/ntp-seguro.sh:
# a HORA em si é do host, isto aqui só define o fuso de leitura.
TZ: ${TZ:-America/Sao_Paulo}
# Endereço público e nome do sistema. Ficam aqui com PADRÃO porque não são
# segredo — assim um .env perdido não leva junto a configuração do
# ambiente. O .env continua mandando: se a variável existir lá, ela vence.
#
# ⚠️ APP_HOST é SÓ O HOST, sem "https://". O código monta os links como
# "https://#{APP_HOST}/motorista" (consolidacao_mailer.rb,
# notificacao_service.rb, gatilhos.rb) — com o esquema no valor sai
# "https://https://..." e todo link de e-mail e WhatsApp quebra.
APP_HOST: ${APP_HOST:-teste.reemtransportes.com.br}
APP_NAME: "${APP_NAME:-Reem Logística}"
# Hosts extras aceitos além do APP_HOST (vírgula separa vários). Com
# RAILS_ENV=production o Rails só aceita os hosts listados; o acesso pela
# rede interna chega com o IP do NAS e era recusado com
# "Blocked hosts: 100.75.222.23:3001". Ver config/environments/production.rb.
HOSTS_PERMITIDOS: ${HOSTS_PERMITIDOS:-100.75.222.23}
# A ponte do WhatsApp é alcançada pelo nome do serviço na rede do compose.
WHATSAPP_URL: ${WHATSAPP_URL:-http://whatsapp:3001}
volumes:
- ".:/app"
- "bundle_cache:/usr/local/bundle"
# Todo o boot (migrations, cron, Puma) mora em bin/docker-boot, com o
# motivo de cada passo comentado lá. Ficava aqui como uma linha só de
# `bash -c`, ilegível e impossível de depurar quando um passo falhava.
#
# `bash` explícito de propósito, em vez de chamar o script direto: a pasta
# do projeto vive num share do NAS e o BIT DE EXECUÇÃO se perde ao copiar
# por SMB/File Station. Sem isto, o deploy morreria com um
# "permission denied" que não tem nada a ver com o script.
command: ["bash", "bin/docker-boot"]
# `unless-stopped`: sobe sozinho depois de queda do processo, de reboot do
# servidor e de `docker compose up`, e SÓ fica parado se alguém der
# `docker compose stop/down` explicitamente. Como o bin/docker-boot roda
# `db:prepare` no começo, isso já entrega a migration automática a cada
# restart — não existe passo manual depois do deploy.
#
# Escolhido em vez de `always` porque `always` reergue o container até
# depois de um `stop` deliberado (num reboot do servidor), tirando do
# operador a chance de deixar o sistema fora do ar de propósito.
restart: unless-stopped
# O banco PostgreSQL já existe externamente.
# Configure DB_HOST no .env com o IP/hostname do seu servidor PostgreSQL.
#
# SEM `depends_on: whatsapp` de propósito: o Rails não precisa da ponte para
# subir nem para funcionar — sem ela, a tela mostra "desconectado" e o envio
# de WhatsApp registra falha no log de envios. Declarar a dependência faria
# um problema no container do WhatsApp respingar no sistema inteiro.
# Ponte com o WhatsApp (Baileys, sessão pareada por QR). Container separado
# porque não existe biblioteca Ruby que fale o protocolo do WhatsApp Web — e
# porque isolar a sessão evita que uma queda dela derrube o Puma.
#
# ⚠️ A porta NÃO é publicada de propósito: quem alcança é só o container do
# Rails, pela rede interna do compose. Publicar exporia um endpoint que
# manda mensagem em nome da empresa.
whatsapp:
build:
context: ./whatsapp
dockerfile: Dockerfile
restart: unless-stopped
environment:
WHATSAPP_TOKEN: ${WHATSAPP_TOKEN}
WHATSAPP_DATA_DIR: /data
PORT: 3001
# Mesmo fuso do Rails: log de envio com hora diferente da do sistema
# torna impossível cruzar os dois na hora de investigar uma falha.
TZ: ${TZ:-America/Sao_Paulo}
volumes:
# A sessão pareada vive aqui. Sem este volume, cada deploy exige escanear
# o QR de novo.
- "whatsapp_auth:/data"
expose:
- "3001"
volumes:
bundle_cache:
whatsapp_auth: