Pular para o conteúdo principal

Banco de dados do deploy (Postgres / SQL Server)

Esta página é o playbook prático para dar um banco a um deploy/tenant. Para a arquitetura dual-engine (Prisma, migrations, imagens) veja Bancos Suportados; para o fluxo completo do tenant veja Adicionar um novo tenant.

A ideia que evita 90% da dor

O app sempre alcança o banco por host.docker.internal:<porta>, e os scripts db-postgres.sh / db-sqlserver.sh leem o MESMO .env que o app. Então você define as variáveis DB_* uma vez no .env.<grupo>, e o container do banco já sobe casado com elas — sem ficar acertando à mão.

O banco roda no seu próprio projeto compose (h1-db-postgres / h1-db-sqlserver), separado do app (h1-stack). Ele pode até estar em outra máquina — o app só precisa da URL/porta certa no .env.

Escolha seu caminho

Você já tem um banco pronto (Postgres no host, ou SQL Server gerenciado/externo)?
├─ SIM → Caminho A (só apontar o .env) → vá para §A
└─ NÃO, quero subir um container com nossos scripts:
├─ Postgres → Caminho B-PG → vá para §B
└─ SQL Server → Caminho B-MS → vá para §B
Quer DB + app num comando só? → Caminho C → vá para §C

Todos os caminhos terminam no mesmo lugar: §Deploy (subir o app) e §Verificar.

Variáveis de conexão — defina uma vez no .env.<grupo>

Postgres (padrão):

DB_ENGINE=postgres            # (default; pode omitir)
POSTGRES_HOST=host.docker.internal
POSTGRES_HOST_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<senha>
HSBR_DB_NAME=ga6

SQL Server:

DB_ENGINE=sqlserver
DB_MSSQL_HOST=host.docker.internal
DB_MSSQL_PORT=1433
DB_MSSQL_USER=sa
DB_MSSQL_SA_PASSWORD=<senha forte>
DB_MSSQL_ENCRYPT=true
DB_MSSQL_TRUST_CERT=true
HSBR_DB_NAME=ga6
Licença é sempre Postgres — mas só se você roda o license server aqui

Num tenant comercial (COMPOSE_PROFILES=hsbr) o license server não roda neste host — o back fala com ele por HTTP (LICENSE_SERVER_URL). Então o único banco que você provisiona é o do H1 Tech (Postgres ou SQL Server). O banco h1_license só importa no host que roda o profile license/all.


§A — Banco já existe (host ou gerenciado/externo)

Use quando há um Postgres já no host, ou um SQL Server gerenciado (Azure SQL, RDS, um servidor da casa do cliente, etc.).

  1. Aponte o .env.<grupo> para ele (host/porta/usuário/senha — tabela acima). Para banco em outra máquina, troque host.docker.internal pelo host real (ex.: sqlserver.cliente.local ou o IP/DNS gerenciado).
  2. Garanta que o banco do H1 Tech existe (o app não cria o database):
    • Postgres: createdb ga6 (ou CREATE DATABASE ga6;).
    • SQL Server: CREATE DATABASE [ga6];.
    • (As tabelas são criadas pelo migrate deploy no boot — você só precisa do database vazio.)
  3. Pule para §Deploy. (Não rode db-*.sh — você não quer um container; já tem banco.)

§B — Subir um container de banco com nossos scripts (split)

Sobe o banco primeiro, no projeto dele, e depois o app. Rode em DevOps/docker/.

Os dois scripts publicam o container no gateway da bridge docker (ex.: 172.17.0.1), não em loopback — é por esse IP que os containers do app resolvem host.docker.internal; um publish em 127.0.0.1 seria invisível para eles (ver Troubleshooting). E ao final eles testam o alcance a partir de um container: se o firewall bloquear, o script morre imprimindo a regra UFW exata, antes do deploy entrar em loop de erro.

B-PG · Postgres

./scripts/db-postgres.sh --env <grupo>

Sobe postgres:16-alpine (projeto h1-db-postgres) em <gateway>:${POSTGRES_HOST_PORT}, com volume h1-pgdata, e no 1º boot cria h1_license + ga6 (via init-dbs.sql). Lê POSTGRES_PASSWORD / POSTGRES_USER / POSTGRES_HOST_PORT / DB_PUBLISH_BIND do .env.

B-MS · SQL Server

Garanta os DB_MSSQL_* no .env (tabela acima), então:

./scripts/db-sqlserver.sh --env <grupo>

Sobe mcr.microsoft.com/mssql/server:2019-latest (projeto h1-db-sqlserver) em <gateway>:${DB_MSSQL_PORT}, com volume h1-mssqldata, espera ficar saudável e cria HSBR_DB_NAME (SQL Server não auto-cria database, então um passo db-init roda o CREATE DATABASE). Lê DB_MSSQL_SA_PASSWORD / DB_MSSQL_PORT / HSBR_DB_NAME / DB_PUBLISH_BIND do .env.

Host já tem SQL Server nativo na 1433?

Confira com ss -ltnp | grep 1433. Se sim, não brigue pela porta: use DB_MSSQL_PORT=14333 no .env — essa única variável controla o publish do container e a conexão do app, então os dois ficam casados automaticamente.

Quando o script retorna (probe ✔), o banco está pronto, saudável e alcançável pelos containers. Vá para §Deploy.


§C — Tudo de uma vez

Não existe um único compose que suba banco e app juntos (são projetos separados de propósito — o banco costuma ser externo). Mas você pode encadear num comando:

# Postgres
./scripts/db-postgres.sh --env <grupo> && ./scripts/deploy-stack.sh <grupo>

# SQL Server
./scripts/db-sqlserver.sh --env <grupo> && ./scripts/deploy-stack.sh <grupo>

O && garante a ordem: o banco fica saudável (os scripts usam --wait) antes do app rodar as migrations. É o caminho §B + §Deploy numa linha.


§Deploy — subir o app (comum a todos os caminhos)

./scripts/deploy-stack.sh <grupo>          # == deploy.sh --env <grupo>

O deploy-stack.sh lê o engine do .env. Se DB_ENGINE=sqlserver, ele layer-a docker-compose.sqlserver.yml automaticamente (imagem …-sqlserver, conexão DB_MSSQL_*, hub desligado). O entrypoint roda prisma migrate deploy (e seed, se HSBR_RUN_SEED=1) no banco que você proveu.

SQL Server precisa da imagem -sqlserver

A imagem GHCR padrão é Postgres. Para SQL Server, a tag …-sqlserver precisa existir no registry (a CI publica), ou builde do fonte: ./scripts/deploy-stack.sh <grupo> --build. Detalhes em Bancos Suportados.

§Verificar

docker ps                                            # banco + app no ar
curl http://localhost:${HSBR_BACK_HOST_PORT}/api/health
curl http://localhost:${HSBR_BACK_HOST_PORT}/license/status # active: true

# Banco direto (opcional):
# Postgres: psql -h 127.0.0.1 -p $POSTGRES_HOST_PORT -U postgres -d $HSBR_DB_NAME -c '\dt' | head
# SQL Server: sqlcmd -S 127.0.0.1,$DB_MSSQL_PORT -U sa -P "$DB_MSSQL_SA_PASSWORD" -C -Q "SELECT name FROM sys.databases"

Parar / apagar o banco

# Postgres
docker compose --project-name h1-db-postgres -f docker-compose.db-postgres.yml down # para (mantém dados)
docker compose --project-name h1-db-postgres -f docker-compose.db-postgres.yml down -v # ⚠ apaga o volume

# SQL Server
docker compose --project-name h1-db-sqlserver -f docker-compose.db-sqlserver.yml down
docker compose --project-name h1-db-sqlserver -f docker-compose.db-sqlserver.yml down -v # ⚠ apaga o volume

Troubleshooting

Sintomas reais de um deploy SQL Server (valem para Postgres-container também):

SintomaCausaFix
Banco (healthy) mas back loopa P1001 (migrate) + ETIMEOUT (seed)Dentro do container, host.docker.internal = gateway da bridge (172.17.0.1), não o loopback do host. Banco publicado em 127.0.0.1 é invisível; ou o UFW dropa o tráfego container→host (é INPUT, e o UFW filtra — diferente dos ports publicados pelo Docker).Os db-*.sh atuais já publicam no gateway e testam. UFW: ufw allow from 172.16.0.0/12 to any port <porta-db> proto tcp
P1000 Authentication failed (sa)Você está acertando outro SQL Server (ex.: um mssql-server nativo na 1433 — systemctl status mssql-server), ou o volume do container guardou uma senha antiga de uma tentativa anterior.Porta dedicada (DB_MSSQL_PORT=14333); ou recriar do zero: docker rm -f h1-db-sqlserver && docker volume rm h1-db-sqlserver_h1-mssqldatadb-sqlserver.sh
db-sqlserver.sh falha: porta em usoAlgo já escuta na DB_MSSQL_PORT (cheque ss -ltnp | grep <porta>).Troque a porta no .env (uma variável só, tudo acompanha)
Back "healthy" mas /user/signin 500O healthcheck não testa o banco; migrate failed — continuing no boot deixou o schema vazio.docker logs <back> | head -30 mostra o erro real; resolva o item acima e docker restart (migrate roda em todo boot)
Login 401 com banco OKSeed nunca rodou (HSBR_RUN_SEED=0 no 1º boot).HSBR_RUN_SEED=1 → re-deploy → volte a 0. Ver Migrations e Seed

Para testar o alcance exatamente como o app (é o probe dos scripts):

docker run --rm --add-host=host.docker.internal:host-gateway \
busybox:stable sh -c "nc -z -w 5 host.docker.internal <porta-db>" && echo OPEN

Notas para SQL Server em produção

  • RAM: SQL Server 2019 quer ~2GB+ — pesado num VPS compartilhado.
  • Licença do SQL Server: o container usa MSSQL_PID=Developer (não licenciado para produção). Para produção, use uma edição licenciada ou um instance gerenciado (Caminho A).
  • Backups: o backup-db.sh é pg_dump (só Postgres). Para SQL Server use BACKUP DATABASE / sqlcmd ou o backup do instance gerenciado.