compose: osrm baixa o grafo sozinho (sem travar deploy) + node v3.3

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hpjc1TdaRAHoYC6wCFw19E
This commit is contained in:
Erico Mac
2026-09-16 20:13:55 -03:00
co-authored by Claude Opus 5
parent e7e43c14f8
commit f3650e545f
2 changed files with 36 additions and 102 deletions
+18 -51
View File
@@ -13,8 +13,8 @@
# Variables do Coolify. EVIDENCE_KEYS: "1:<openssl rand -base64 32>" (guarde cópia!). # Variables do Coolify. EVIDENCE_KEYS: "1:<openssl rand -base64 32>" (guarde cópia!).
# • Certificado A1 (ingestor, dfe-worker, backend): DFE_CERT_PFX_BASE64 + DFE_CERT_PASSPHRASE # • Certificado A1 (ingestor, dfe-worker, backend): DFE_CERT_PFX_BASE64 + DFE_CERT_PASSPHRASE
# como variáveis secretas no Coolify — sem montar arquivo no servidor. # como variáveis secretas no Coolify — sem montar arquivo no servidor.
# • Drenagem: ingestor (ONE) + dfe-worker (cadeia) + osrm. O grafo (15 GB) é baixado 1 vez # • Drenagem: ingestor (ONE) + dfe-worker (cadeia) + osrm. O próprio osrm baixa o grafo
# pelo osrm-data para o volume osrm_data (OSRM_DATA_URL nas Environment Variables). # (15 GB) 1 vez para o volume osrm_data (OSRM_DATA_URL nas Environment Variables).
# ============================================================================ # ============================================================================
x-app-env: x-app-env:
DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public' DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public'
@@ -73,56 +73,22 @@ services:
- gotenberg - gotenberg
- '--chromium-disable-javascript=false' - '--chromium-disable-javascript=false'
- '--api-timeout=60s' - '--api-timeout=60s'
osrm-data: osrm:
# Baixa UMA VEZ o grafo OSRM do Brasil (15 GB, pré-processado) para o volume osrm_data, # Rotas pelas vias (grafo do Brasil, MLD, v5.26.0). Na 1ª subida BAIXA o grafo
# confere o sha256 de cada arquivo e marca .pronto. Próximos deploys: sai na hora. # (15 GB) de OSRM_DATA_URL para o volume osrm_data (retoma e confere sha256); nas
# OSRM_DATA_URL (Environment Variables) = endereço temporário de onde baixar. # seguintes só roteia. Serviço de longa duração: o deploy não fica esperando o
image: 'gitea.externo.utic.app.br/ericoalmeida/curl:8.15.0' # download. --mmap: ~70-700 MB de RAM. O dfe-worker só começa com o OSRM roteando.
restart: 'no' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-osrm:v1'
user: root restart: unless-stopped
environment: environment:
OSRM_DATA_URL: '${OSRM_DATA_URL}' OSRM_DATA_URL: '${OSRM_DATA_URL}'
volumes: volumes:
- 'osrm_data:/data' - 'osrm_data:/data'
entrypoint:
- sh
- '-c'
- |
set -e
cd /data
if [ -f .pronto ]; then echo "grafo OSRM já presente"; exit 0; fi
if [ -z "$$OSRM_DATA_URL" ]; then echo "defina OSRM_DATA_URL"; exit 1; fi
curl -fsS --retry 10 --retry-all-errors "$$OSRM_DATA_URL/SHA256SUMS" -o SHA256SUMS
for f in $$(awk '{print $$2}' SHA256SUMS); do
echo "baixando $$f"
curl -fS --retry 20 --retry-all-errors --retry-delay 5 -C - "$$OSRM_DATA_URL/$$f" -o "$$f"
done
sha256sum -c SHA256SUMS
touch .pronto
echo "grafo OSRM pronto"
osrm:
# Rotas pelas vias (grafo do Brasil, MLD, v5.26.0). --mmap: lê o grafo do disco sob
# demanda (~70-700 MB de RAM em vez de ~15 GB). Leva ~40 s para aceitar rotas.
image: 'gitea.externo.utic.app.br/ericoalmeida/osrm-backend:latest'
restart: unless-stopped
depends_on:
osrm-data:
condition: service_completed_successfully
command:
- osrm-routed
- '--algorithm'
- mld
- '--mmap'
- '--max-matching-size'
- '2000'
- /data/brazil.osrm
volumes:
- 'osrm_data:/data:ro'
expose: expose:
- '5000' - '5000'
ingestor: ingestor:
# DRENAGEM do ONE (passagens + fotos). Valores de cadência da produção antiga. # DRENAGEM do ONE (passagens + fotos). Valores de cadência da produção antiga.
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
db: db:
@@ -158,7 +124,7 @@ services:
MINIO_BUCKET: rastro-photos MINIO_BUCKET: rastro-photos
command: 'sh -c "wait-for-db schema rabbitmq && pnpm --filter @rastro/ingestor start"' command: 'sh -c "wait-for-db schema rabbitmq && pnpm --filter @rastro/ingestor start"'
migrate: migrate:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: 'no' restart: 'no'
depends_on: depends_on:
db: db:
@@ -172,7 +138,7 @@ services:
DB_CONNECTION_LIMIT: '5' DB_CONNECTION_LIMIT: '5'
command: 'sh -c "wait-for-db && pnpm --filter @rastro/db migrate && pnpm --filter @rastro/db postgis && pnpm --filter @rastro/db timescale && pnpm --filter @rastro/db intel && pnpm --filter @rastro/db analyze && pnpm --filter @rastro/db restore-users"' command: 'sh -c "wait-for-db && pnpm --filter @rastro/db migrate && pnpm --filter @rastro/db postgis && pnpm --filter @rastro/db timescale && pnpm --filter @rastro/db intel && pnpm --filter @rastro/db analyze && pnpm --filter @rastro/db restore-users"'
processor: processor:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
db: db:
@@ -200,7 +166,7 @@ services:
command: 'sh -c "wait-for-db schema rabbitmq && pnpm --filter @rastro/processor start"' command: 'sh -c "wait-for-db schema rabbitmq && pnpm --filter @rastro/processor start"'
dfe-worker: dfe-worker:
# Cadeia MDF-e → CT-e → NF-e (SEFAZ; Teradata para transporte além de D+1) + rota OSRM. # Cadeia MDF-e → CT-e → NF-e (SEFAZ; Teradata para transporte além de D+1) + rota OSRM.
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
db: db:
@@ -238,7 +204,8 @@ services:
DFE_HOT_DAYS: '7' DFE_HOT_DAYS: '7'
DFE_OPEN_MAX_DAYS: '60' DFE_OPEN_MAX_DAYS: '60'
TD_CHAIN_MIN_AGE_HOURS: '36' TD_CHAIN_MIN_AGE_HOURS: '36'
command: 'sh -c "wait-for-db schema && pnpm --filter @rastro/processor start:worker"' # wait-for-db osrm: sem OSRM roteando, a rota seria gravada como RETA (fallback).
command: 'sh -c "wait-for-db schema osrm && pnpm --filter @rastro/processor start:worker"'
analytics: analytics:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-analytics:v4' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-analytics:v4'
restart: unless-stopped restart: unless-stopped
@@ -259,7 +226,7 @@ services:
TERADATA_USER: '${TERADATA_USER}' TERADATA_USER: '${TERADATA_USER}'
TERADATA_PASSWORD: '${TERADATA_PASSWORD}' TERADATA_PASSWORD: '${TERADATA_PASSWORD}'
backend: backend:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
db: db:
@@ -306,7 +273,7 @@ services:
- traefik.http.routers.rastroapi.priority=1000 - traefik.http.routers.rastroapi.priority=1000
- traefik.http.services.rastroapi.loadbalancer.server.port=39010 - traefik.http.services.rastroapi.loadbalancer.server.port=39010
web: web:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
environment: environment:
DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public' DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public'
@@ -319,7 +286,7 @@ services:
expose: expose:
- '39000' - '39000'
admin: admin:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
environment: environment:
DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public' DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public'
+18 -51
View File
@@ -13,8 +13,8 @@
# Variables do Coolify. EVIDENCE_KEYS: "1:<openssl rand -base64 32>" (guarde cópia!). # Variables do Coolify. EVIDENCE_KEYS: "1:<openssl rand -base64 32>" (guarde cópia!).
# • Certificado A1 (ingestor, dfe-worker, backend): DFE_CERT_PFX_BASE64 + DFE_CERT_PASSPHRASE # • Certificado A1 (ingestor, dfe-worker, backend): DFE_CERT_PFX_BASE64 + DFE_CERT_PASSPHRASE
# como variáveis secretas no Coolify — sem montar arquivo no servidor. # como variáveis secretas no Coolify — sem montar arquivo no servidor.
# • Drenagem: ingestor (ONE) + dfe-worker (cadeia) + osrm. O grafo (15 GB) é baixado 1 vez # • Drenagem: ingestor (ONE) + dfe-worker (cadeia) + osrm. O próprio osrm baixa o grafo
# pelo osrm-data para o volume osrm_data (OSRM_DATA_URL nas Environment Variables). # (15 GB) 1 vez para o volume osrm_data (OSRM_DATA_URL nas Environment Variables).
# ============================================================================ # ============================================================================
x-app-env: x-app-env:
DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public' DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public'
@@ -73,56 +73,22 @@ services:
- gotenberg - gotenberg
- '--chromium-disable-javascript=false' - '--chromium-disable-javascript=false'
- '--api-timeout=60s' - '--api-timeout=60s'
osrm-data: osrm:
# Baixa UMA VEZ o grafo OSRM do Brasil (15 GB, pré-processado) para o volume osrm_data, # Rotas pelas vias (grafo do Brasil, MLD, v5.26.0). Na 1ª subida BAIXA o grafo
# confere o sha256 de cada arquivo e marca .pronto. Próximos deploys: sai na hora. # (15 GB) de OSRM_DATA_URL para o volume osrm_data (retoma e confere sha256); nas
# OSRM_DATA_URL (Environment Variables) = endereço temporário de onde baixar. # seguintes só roteia. Serviço de longa duração: o deploy não fica esperando o
image: 'gitea.externo.utic.app.br/ericoalmeida/curl:8.15.0' # download. --mmap: ~70-700 MB de RAM. O dfe-worker só começa com o OSRM roteando.
restart: 'no' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-osrm:v1'
user: root restart: unless-stopped
environment: environment:
OSRM_DATA_URL: '${OSRM_DATA_URL}' OSRM_DATA_URL: '${OSRM_DATA_URL}'
volumes: volumes:
- 'osrm_data:/data' - 'osrm_data:/data'
entrypoint:
- sh
- '-c'
- |
set -e
cd /data
if [ -f .pronto ]; then echo "grafo OSRM já presente"; exit 0; fi
if [ -z "$$OSRM_DATA_URL" ]; then echo "defina OSRM_DATA_URL"; exit 1; fi
curl -fsS --retry 10 --retry-all-errors "$$OSRM_DATA_URL/SHA256SUMS" -o SHA256SUMS
for f in $$(awk '{print $$2}' SHA256SUMS); do
echo "baixando $$f"
curl -fS --retry 20 --retry-all-errors --retry-delay 5 -C - "$$OSRM_DATA_URL/$$f" -o "$$f"
done
sha256sum -c SHA256SUMS
touch .pronto
echo "grafo OSRM pronto"
osrm:
# Rotas pelas vias (grafo do Brasil, MLD, v5.26.0). --mmap: lê o grafo do disco sob
# demanda (~70-700 MB de RAM em vez de ~15 GB). Leva ~40 s para aceitar rotas.
image: 'gitea.externo.utic.app.br/ericoalmeida/osrm-backend:latest'
restart: unless-stopped
depends_on:
osrm-data:
condition: service_completed_successfully
command:
- osrm-routed
- '--algorithm'
- mld
- '--mmap'
- '--max-matching-size'
- '2000'
- /data/brazil.osrm
volumes:
- 'osrm_data:/data:ro'
expose: expose:
- '5000' - '5000'
ingestor: ingestor:
# DRENAGEM do ONE (passagens + fotos). Valores de cadência da produção antiga. # DRENAGEM do ONE (passagens + fotos). Valores de cadência da produção antiga.
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
db: db:
@@ -158,7 +124,7 @@ services:
MINIO_BUCKET: rastro-photos MINIO_BUCKET: rastro-photos
command: 'sh -c "wait-for-db schema rabbitmq && pnpm --filter @rastro/ingestor start"' command: 'sh -c "wait-for-db schema rabbitmq && pnpm --filter @rastro/ingestor start"'
migrate: migrate:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: 'no' restart: 'no'
depends_on: depends_on:
db: db:
@@ -172,7 +138,7 @@ services:
DB_CONNECTION_LIMIT: '5' DB_CONNECTION_LIMIT: '5'
command: 'sh -c "wait-for-db && pnpm --filter @rastro/db migrate && pnpm --filter @rastro/db postgis && pnpm --filter @rastro/db timescale && pnpm --filter @rastro/db intel && pnpm --filter @rastro/db analyze && pnpm --filter @rastro/db restore-users"' command: 'sh -c "wait-for-db && pnpm --filter @rastro/db migrate && pnpm --filter @rastro/db postgis && pnpm --filter @rastro/db timescale && pnpm --filter @rastro/db intel && pnpm --filter @rastro/db analyze && pnpm --filter @rastro/db restore-users"'
processor: processor:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
db: db:
@@ -200,7 +166,7 @@ services:
command: 'sh -c "wait-for-db schema rabbitmq && pnpm --filter @rastro/processor start"' command: 'sh -c "wait-for-db schema rabbitmq && pnpm --filter @rastro/processor start"'
dfe-worker: dfe-worker:
# Cadeia MDF-e → CT-e → NF-e (SEFAZ; Teradata para transporte além de D+1) + rota OSRM. # Cadeia MDF-e → CT-e → NF-e (SEFAZ; Teradata para transporte além de D+1) + rota OSRM.
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
db: db:
@@ -238,7 +204,8 @@ services:
DFE_HOT_DAYS: '7' DFE_HOT_DAYS: '7'
DFE_OPEN_MAX_DAYS: '60' DFE_OPEN_MAX_DAYS: '60'
TD_CHAIN_MIN_AGE_HOURS: '36' TD_CHAIN_MIN_AGE_HOURS: '36'
command: 'sh -c "wait-for-db schema && pnpm --filter @rastro/processor start:worker"' # wait-for-db osrm: sem OSRM roteando, a rota seria gravada como RETA (fallback).
command: 'sh -c "wait-for-db schema osrm && pnpm --filter @rastro/processor start:worker"'
analytics: analytics:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-analytics:v4' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-analytics:v4'
restart: unless-stopped restart: unless-stopped
@@ -259,7 +226,7 @@ services:
TERADATA_USER: '${TERADATA_USER}' TERADATA_USER: '${TERADATA_USER}'
TERADATA_PASSWORD: '${TERADATA_PASSWORD}' TERADATA_PASSWORD: '${TERADATA_PASSWORD}'
backend: backend:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
db: db:
@@ -306,7 +273,7 @@ services:
- traefik.http.routers.rastroapi.priority=1000 - traefik.http.routers.rastroapi.priority=1000
- traefik.http.services.rastroapi.loadbalancer.server.port=39010 - traefik.http.services.rastroapi.loadbalancer.server.port=39010
web: web:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
environment: environment:
DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public' DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public'
@@ -319,7 +286,7 @@ services:
expose: expose:
- '39000' - '39000'
admin: admin:
image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.2' image: 'gitea.externo.utic.app.br/ericoalmeida/rastro-node:v3.3'
restart: unless-stopped restart: unless-stopped
environment: environment:
DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public' DATABASE_URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public'