Files
CRM_AGENTES_CARGA/docker-compose.e2e.yml
marcos dfb3c8a08d chore(dev): puertos del CRM sin choque con EFC y overrides locales fuera del repo
El 8000 del host lo ocupa EFC_backend_dev, asi que el backend del stack E2E se
mueve a 3468 (vecino del 3467 de prod). Dentro del contenedor sigue siendo 8000:
gunicorn, healthcheck e INTERNAL_API_URL son de la red interna y no cambian.
El 5173 NO se mueve: es la redirect URI registrada en Workspace.

SUNRISE/, automatizacion/ y docker-compose.dev.yml quedan fuera del control de
versiones: son el corredor de la corrida autonoma y el override de dev de cada
maquina, no configuracion compartida.

Ref: T2026-08-046

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 10:19:09 -06:00

189 lines
7.4 KiB
YAML

# Stack efímero para pruebas E2E (Playwright) en CI.
# Levantado por Jenkinsfile (stage "E2E (Playwright)") ANTES del deploy a dev,
# para validar la imagen recién buildeada contra una DB limpia y servicios aislados.
#
# Diferencias clave vs docker-compose.prod.yml:
# - Sin volúmenes persistidos (todo se descarta en `down -v`).
# - Sin `container_name` ni `restart` (efímero, COMPOSE_PROJECT_NAME aísla los nombres).
# - Sin `celery_worker` / `celery_beat` (no se ejercitan en los specs actuales).
# - Imágenes vía env vars: la del frontend se rebuildea localmente con
# VITE_API_URL=http://localhost:3468/api/ (la prod tiene la URL de dev bakeada).
#
# PUERTOS DEL HOST — 2026-08-10
# frontend 5173 NO SE MUEVE. Está registrado en Workspace: `http://localhost:5173/auth/callback`
# es la redirect URI permitida del cliente OIDC, y es además el `baseURL` de
# Playwright, el `CORS_ORIGINS` y el `APP_PUBLIC_URL` del backend. Moverlo rompe
# el login antes de que corra el primer spec.
# backend 3468 Movido desde 8000. En la máquina de desarrollo el 8000 del host lo ocupa
# `EFC_backend_dev` (stack de EFC), así que este servicio no arrancaba:
# "port is already allocated". 3468 es vecino del 3467 de docker-compose.prod.yml,
# para que los puertos del CRM se mantengan en un mismo rango reconocible.
# Dentro del contenedor sigue siendo 8000: el bind de gunicorn, el healthcheck
# y `INTERNAL_API_URL=http://backend:8000` NO cambian, son de la red interna.
#
# ⚠️ SI SE REACTIVA EL STAGE E2E DEL JENKINSFILE: la imagen del frontend hay que reconstruirla
# con VITE_API_URL=http://localhost:3468/api/. Si se hornea con 8000, el navegador de Playwright
# pegaría contra el backend de EFC y los specs pasarían contra el sistema equivocado — no falla,
# miente. Es el modo de fallo caro de este cambio.
#
# Variables requeridas en el entorno al invocar docker compose:
# E2E_BACKEND_IMAGE — imagen del backend recién pusheada a Harbor
# E2E_FRONTEND_IMAGE — imagen temporal del frontend con VITE_API_URL=localhost:3468
services:
postgres-app:
image: postgres:18-alpine
environment:
POSTGRES_DB: app_core
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_INITDB_ARGS: "--encoding=UTF8"
networks:
- e2e-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d app_core || exit 1"]
interval: 5s
timeout: 3s
retries: 10
start_period: 20s
# Postgres 18+ requiere mount en /var/lib/postgresql (padre), no en /data.
# Ver https://github.com/docker-library/postgres/pull/1259 — la imagen detecta
# el mount viejo como "unused" y aborta el arranque.
tmpfs:
- /var/lib/postgresql
minio:
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
networks:
- e2e-net
healthcheck:
test: ["CMD-SHELL", "curl -f http://127.0.0.1:9000/minio/health/live || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 15s
tmpfs:
- /data
valkey:
image: valkey/valkey:7.2
networks:
- e2e-net
backend:
image: ${E2E_BACKEND_IMAGE}
environment:
- DEBUG=False
- ENVIRONMENT=e2e
- PYTHONUNBUFFERED=1
- PYTHONDONTWRITEBYTECODE=1
- CORE_DB_HOST=postgres-app
- CORE_DB_PORT=5432
- CORE_DB_NAME=app_core
- CORE_DB_USER=postgres
- CORE_DB_PASSWORD=postgres
# Keycloak — apunta a Workspace real; el cliente anexo76-frontend ya
# tiene http://localhost:5173/auth/callback como redirect URI permitida.
- KEYCLOAK_SERVER_URL=https://workspace.aduanasoft.com/kcauth
- KEYCLOAK_REALM=master
- KEYCLOAK_CLIENT_ID=anexo76-frontend
- KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET:-}
- CORS_ORIGINS=http://localhost:5173
- VALKEY_URL=redis://valkey:6379/0
- HUB_URL=https://workspace.aduanasoft.com
- APP_PUBLIC_URL=http://localhost:5173
# SITAR — proveedor del tipo de cambio (botón "Consultar DOF" del dialog
# de ExchangeRateGuard). Sin estas vars el dialog nunca llena el input
# y auth.setup.ts falla. Las credenciales se inyectan desde Jenkins.
- SITAR_API_URL=${SITAR_API_URL:-}
- SITAR_API_USER=${SITAR_API_USER:-}
- SITAR_API_PASSWORD=${SITAR_API_PASSWORD:-}
- CSV_IMPORT_STORAGE=minio
- S3_ENDPOINT_URL=http://minio:9000
- S3_ACCESS_KEY=minioadmin
- S3_SECRET_KEY=minioadmin
- S3_BUCKET=anexo76
- S3_REGION=us-east-1
- S3_USE_SSL=false
- S3_FILE_STORAGE=true
ports:
# 3468 en el HOST, 8000 dentro del contenedor. Ver la nota de puertos del encabezado:
# el 8000 del host lo ocupa EFC_backend_dev en la maquina de desarrollo.
- "3468:8000"
depends_on:
postgres-app:
condition: service_healthy
minio:
condition: service_healthy
networks:
- e2e-net
# Replica el comando de prod (gunicorn) para que el test ejerza el mismo runtime
# que se desplegará. El CMD del Dockerfile usa uvicorn --reload (modo dev).
command:
- gunicorn
- main:app
- -k
- uvicorn.workers.UvicornWorker
- -w
- "1"
- -b
- 0.0.0.0:8000
- --log-level
- info
- --forwarded-allow-ips
- "*"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/api/health || exit 1"]
interval: 10s
timeout: 5s
retries: 10
start_period: 60s
frontend:
image: ${E2E_FRONTEND_IMAGE}
environment:
- NODE_ENV=production
# VITE_API_URL ya está bakeada en E2E_FRONTEND_IMAGE; este valor solo sirve
# para fallback server-side en frontend/src/lib/server/api.ts.
#
# ⚠️ El puerto del host es 3468, no 8000 (ver el encabezado). Y como el valor que usa
# el NAVEGADOR va bakeado en la imagen, cambiar solo esta línea NO basta: quien
# reconstruya E2E_FRONTEND_IMAGE tiene que hornear la misma URL.
- VITE_API_URL=http://localhost:3468/api/
- INTERNAL_API_URL=http://backend:8000/api/
- INTERNAL_HUB_URL=https://workspace.aduanasoft.com
- HUB_URL=https://workspace.aduanasoft.com
- VITE_HUB_URL=https://workspace.aduanasoft.com
- VITE_KEYCLOAK_URL=https://workspace.aduanasoft.com/kcauth
- VITE_KEYCLOAK_REALM=master
- VITE_KEYCLOAK_CLIENT_ID=anexo76-frontend
- KEYCLOAK_URL=https://workspace.aduanasoft.com/kcauth
- KEYCLOAK_REALM=master
- KEYCLOAK_CLIENT_ID=anexo76-frontend
- KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET:-}
# ORIGIN controla url.origin y el flag secure de cookies — debe coincidir con la URL
# registrada en Workspace para que el callback de Keycloak resuelva correctamente.
- ORIGIN=http://localhost:5173
- SITE_URL=http://localhost:5173
ports:
- "5173:5173"
depends_on:
backend:
condition: service_healthy
networks:
- e2e-net
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:5173/ || exit 1"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
networks:
e2e-net:
driver: bridge