Skip to content

feat: docker compose sobe a plataforma inteira - #54

Merged
janeiaraujo merged 1 commit into
mainfrom
feat/docker-completo
Aug 4, 2026
Merged

feat: docker compose sobe a plataforma inteira#54
janeiaraujo merged 1 commit into
mainfrom
feat/docker-completo

Conversation

@janeiaraujo

Copy link
Copy Markdown
Owner

O docker-compose.yml só tinha MongoDB. Quem clonava ainda precisava instalar
Node, rodar npm install nos dois pacotes, configurar .env e subir dois
processos — só para ver a aplicação. Para quem chega pelo post de lançamento,
essa é a maior barreira que existe.

Agora:

docker compose up -d
docker compose --profile demo run --rm seed

e a plataforma responde em http://localhost:8080.

Dois bugs que só apareceram ao subir de verdade

Construí as imagens, subi a stack e exercitei o fluxo completo. Nenhuma leitura
de código teria mostrado estes dois:

1. NotificationContext fixava a porta 3000. A URL do WebSocket era montada
com hostname + ':3000'. Atrás de qualquer proxy isso quebra — e no compose a
porta 3000 nem é exposta no host. Passa a derivar de window.location.host,
como o hook irmão (useRealTimeNotifications) já fazia.

2. Minha primeira versão do nginx tinha o caminho errado. Fiz proxy de
/ws, mas a rota real é /api/ws/notifications — e o location /api/ genérico
não repassa os cabeçalhos de Upgrade, então o handshake falharia de
qualquer forma. Agora há um location /api/ws próprio, declarado antes do
genérico.

Antes: HTTP/1.1 404 Not Found. Depois: HTTP/1.1 101 Switching Protocols.

As imagens

Backend — multi-stage: as dependências de produção são instaladas numa
camada separada, então a imagem final não carrega ESLint nem o runner de testes.
Roda como usuário sem privilégio (node), com healthcheck próprio.

Frontend — compila com Node e serve com nginx. O resultado do build é
estático; não há motivo para carregar Node em produção só para servir arquivo.
O nginx faz cache longo e imutável nos assets com hash no nome (senão o ganho do
code splitting se perderia), no-cache no index.html, e fallback de SPA para
F5 numa rota interna não devolver 404.

Seed fica sob o profile demo porque não é idempotente — rodar a cada
boot criaria organizações e usuários duplicados. O migrate roda sempre, esse é.

Verificação — subi e testei

docker compose up -d 3 containers, todos healthy
GET / e GET /kb/123 200 (fallback de SPA funcionando)
GET /health via proxy {"status":"ok","mongodb":"connected"}
GET /api/records sem token 401
login com o usuário demo token de 223 chars
GET /api/records autenticado 3 KBs, via nginx → backend → mongo
i18n da API pelo proxy Record not found / Registro não encontrado
WebSocket 101 Switching Protocols
cache dos assets public, immutable, max-age=31536000
docker compose --profile demo run --rm seed credenciais criadas

Os READMEs (pt e en) ganharam uma seção "só quero ver funcionando" no topo do
Começando, com o aviso de que este compose é para avaliação e que os segredos
precisam ser trocados antes de qualquer exposição.

O compose so tinha MongoDB: quem clonava ainda precisava instalar Node,
rodar npm install nos dois pacotes, configurar .env e subir dois
processos so para ver a aplicacao. Para quem chega pelo post de
lancamento, isso e a maior barreira que existe.

Agora 'docker compose up -d' sobe banco, API e interface, e tudo
responde em http://localhost:8080. A interface e servida por nginx, que
faz o proxy de /api e do WebSocket - assim so uma porta precisa existir
no host, e o navegador nunca precisa saber o endereco do backend.

Subir de verdade encontrou dois bugs que nenhuma leitura de codigo teria
mostrado:

1. o NotificationContext montava a URL do WebSocket com
   hostname + ':3000' fixo. Atras de qualquer proxy isso quebra - no
   compose a porta 3000 nem existe no host. Passa a derivar de
   window.location.host, como o hook irmao ja fazia;

2. minha primeira versao do nginx fazia proxy de /ws, mas a rota real e
   /api/ws/notifications - e o location /api/ generico nao repassa os
   cabecalhos de Upgrade, entao o handshake falharia de qualquer forma.
   Agora ha um location proprio, antes do generico.

As imagens sao multi-stage: o backend fica sem devDependencies e roda
como usuario sem privilegio; o frontend compila com Node e serve com
nginx, sem carregar Node em producao.

O seed fica sob o profile 'demo' porque nao e idempotente - rodar a cada
boot criaria organizacoes duplicadas. O migrate roda sempre, esse e.
Copilot AI review requested due to automatic review settings August 3, 2026 23:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Este PR reduz drasticamente a barreira de entrada para avaliar a plataforma localmente, passando a subir backend + frontend (nginx) + MongoDB via docker compose, além de ajustar o WebSocket para funcionar atrás de proxy.

Changes:

  • Adiciona imagens Docker multi-stage para backend e frontend (nginx servindo estáticos e fazendo proxy).
  • Atualiza o docker-compose.yml para subir a stack completa e incluir um seed sob profile demo.
  • Corrige a montagem da URL do WebSocket no frontend e documenta o “só quero ver funcionando” nos READMEs.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Adiciona guia rápido de execução via Docker Compose e aviso de troca de segredos.
README.en.md Versão em inglês do guia rápido via Docker Compose.
frontend/src/contexts/NotificationContext.jsx Corrige host/porta do WebSocket para operar atrás de proxy (usa window.location.host).
frontend/nginx.conf Configura SPA fallback, cache de assets e proxy de /api e WebSocket.
frontend/Dockerfile Build do frontend com Node e runtime nginx com healthcheck.
frontend/.dockerignore Reduz contexto de build do frontend.
docker-compose.yml Sobe stack completa (mongo, backend, frontend) e seed opcional via profile.
backend/Dockerfile Build multi-stage com deps prod-only, usuário não privilegiado e healthcheck.
backend/.dockerignore Reduz contexto de build do backend.
Suppressed comments (1)

docker-compose.yml:98

  • Se o volume de uploads não for montado por padrão, a definição do volume uploads fica sem uso e pode ser removida para evitar confusão.
volumes:
  mongo_data:
  uploads:

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docker-compose.yml
Comment on lines +43 to +46
JWT_SECRET: ${JWT_SECRET:-troque-este-segredo-antes-de-usar-de-verdade}
JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-troque-este-refresh-tambem}
FRONTEND_URL: ${FRONTEND_URL:-http://localhost:8080}
# Integracoes externas sao opcionais: sem elas a aplicacao sobe e apenas
Comment thread docker-compose.yml
Comment on lines +49 to +51
volumes:
# Fallback local de upload, usado quando o R2 nao esta configurado.
- uploads:/app/uploads
@janeiaraujo
janeiaraujo merged commit a3432ec into main Aug 4, 2026
5 checks passed
@janeiaraujo janeiaraujo mentioned this pull request Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants