Despliegue
Tres artefactos distintos, con tres caminos distintos.
Backend — Docker Compose
docker-compose.yml levanta un container por rol, todos desde la misma imagen:
| Container | Rol |
|---|---|
node-app | La API HTTP (clusterizada por cores) |
bot-publisher | Scraper PAMI |
bot-consumer-1..4 | Consumidores de la cola de PAMI |
bot-authorization | Sync de autorizaciones |
rabbitmq | Broker (rabbitmq:3.11-management, panel en el 15672) |
nginx_proxy | Reverse proxy y estáticos (puertos 80 / 443) |
socket-server | Servidor de sockets |
Los workers se diferencian solo por su EXECUTION_MODE y tienen límites de recursos propios
(512 MB / 0.5 CPU en el publisher). Ver
Workers y colas.
La imagen
Dockerfile multi-stage:
# Stage 1: node:20, npm install completo, npm run build (tsc → dist/)
# Stage 2: node:20-slim, npm install --production, copia dist/ y certs/
CMD ["node", "dist/index.js"]
.env no va en la imagenSe monta por env_file: .env desde el host. No lo copies al Dockerfile.
Los uploads se persisten con un volumen: /var/uploads del host → /usr/src/app/uploads.
Nginx
Sirve la consola web como estático desde /var/www/oxitec-web-app y proxea la API:
location /api {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://node-app:3000;
# + headers de upgrade para websockets
}
location /mobile/ { # los APK de BullStock para descarga directa
alias /var/www/mobile/;
}
Por eso el front apunta a .../api/v1 y el backend expone /v1: el prefijo /api lo saca
nginx.
Consola web — build estático
npm run build:prod # producción
npm run build:pre # PRE: genera el environment desde env vars y compila
Salida: dist/oxitesa-front/browser. Se publica de dos formas según el ambiente:
- Copiando el build a
/var/www/oxitec-web-appen el server (lo que sirve nginx). - Firebase Hosting — hay un
firebase.jsonconpublic: dist/oxitesa-front/browsery un rewrite**→/index.htmlpara el ruteo del SPA.
build:pre genera el environment en tiempo de buildscripts/set-env.js escribe src/environments/environment-pre.ts a partir de variables de entorno
(API_URL, CLERK_PUBLISHABLE_KEY, FIREBASE_*, POSTHOG_*, POWER_BI_TENANT_ID…). Así las claves
de PRE no quedan committeadas en el repo. Las de producción sí están en el
environment.ts versionado.
Mobile — EAS y builds locales
EAS (la vía normal)
npm run build:dev:android # dev client
npm run build:pre:android # PRE, distribución interna
Perfiles en eas.json:
| Perfil | Qué produce |
|---|---|
development | Dev client, distribución interna |
preview | APK, distribución interna |
production | AAB para Play Store, con autoIncrement y appVersionSource: remote |
Local (Makefile)
make android-release ENV=prod # APK
make android-bundle ENV=prod # AAB
Envuelve expo prebuild + Gradle, y copia el .env elegido a .env antes de compilar para que
los valores queden horneados.
Versionado y update obligatorio
Después de publicar, hay que dar de alta la versión en el módulo mobileConfig del backend
(versión semver, entorno, URL del build, changelog). La app compara su versión contra esa fila al
arrancar y muestra el modal de actualización obligatoria si corresponde.
Los APK para descarga directa se publican en /var/www/mobile/, que nginx sirve en /mobile/. La
consola web tiene una landing de descarga en /download/mobile/bullstock.
Cambios de base de datos
No hay migraciones automáticas de schema. Los cambios se aplican a mano:
| Tipo | Dónde vive | Cómo se aplica |
|---|---|---|
| DDL, stored procedures, views | migrations/**/*.sql | Se ejecuta el SQL contra la base del ambiente |
| Datos de configuración (roles, permisos, estados, tipos de movimiento) | src/migrations/*.ts | npx ts-node — pero los workers también los corren al arrancar |
store/, no el de fix/store/ es el estado completo actual. fix/ son parches históricos que quedan como registro.
Ver Stored procedures.
Orden recomendado de un release
- Base: aplicar el SQL nuevo (SPs, views, DDL) en el ambiente.
- Backend:
docker compose build && docker compose up -d. Verificar que los workers levanten. - Consola web: build y publicar.
- Mobile: build EAS, y recién después dar de alta la versión en
mobileConfig.
El paso 1 va primero porque el backend nuevo suele asumir el SP nuevo, y el paso 4 va último porque dar de alta la versión fuerza la actualización en los dispositivos.