diff --git a/apps/web/nginx.conf b/apps/web/nginx.conf index faf4c29..10fb10f 100644 --- a/apps/web/nginx.conf +++ b/apps/web/nginx.conf @@ -1,4 +1,6 @@ # Same-origin API for the SPA: REST under /api, GraphQL (HTTP + WebSocket) under /graphql. +# The API is reached by its unique alias (task-stream-api), not by the service name `api`: +# on a shared network (Dokploy) another project's `api` would get half of the requests. map $http_upgrade $connection_upgrade { default upgrade; '' close; @@ -9,13 +11,13 @@ server { root /usr/share/nginx/html; location /api/ { - proxy_pass http://api:3000; + proxy_pass http://task-stream-api:3000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /graphql { - proxy_pass http://api:3000; + proxy_pass http://task-stream-api:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; diff --git a/docker-compose.yml b/docker-compose.yml index a5f6973..7f7df2f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,10 @@ # No ports are published here: services only talk over the compose network, and the web is # exposed through the platform's proxy (Dokploy domain → service `web`, port 80). # +# Services talk to each other by unique aliases (task-stream-*), never by the bare service +# name: on a shared network (Dokploy's dokploy-network) other projects also have an `api`, +# `postgres` or `redis`, and Docker DNS would hand out theirs too. +# # Locally, `docker compose` also loads docker-compose.override.yml, which publishes the ports: # docker compose up -d --build → everything: web on http://localhost:8080 # docker compose up -d postgres mongo redis → only infrastructure (then `npx nx serve api` / `npx nx serve web`) @@ -16,6 +20,7 @@ services: secrets: [nexus_token] image: task-stream-web expose: ['80'] + networks: [default] depends_on: api: { condition: service_healthy } restart: unless-stopped @@ -27,12 +32,15 @@ services: secrets: [nexus_token] image: task-stream-api expose: ['3000'] + networks: + default: + aliases: [task-stream-api] environment: - POSTGRES_URL: postgres://taskstream:taskstream@postgres:5432/taskstream + POSTGRES_URL: postgres://taskstream:taskstream@task-stream-postgres:5432/taskstream # No migrations yet: TypeORM creates the event store and lookup tables. POSTGRES_SYNCHRONIZE: 'true' - MONGO_URL: mongodb://mongo:27017/taskstream_read - REDIS_URL: redis://redis:6379 + MONGO_URL: mongodb://task-stream-mongo:27017/taskstream_read + REDIS_URL: redis://task-stream-redis:6379 EVENT_STREAM_KEY: task-stream:events EVENTS_BRIDGE_ENABLED: 'true' PIREON_BASE_URL: https://oauth.pireon.dev @@ -40,8 +48,10 @@ services: PIREON_CLIENT_ID: ${PIREON_CLIENT_ID:-} PIREON_CLIENT_SECRET: ${PIREON_CLIENT_SECRET:-} GRAPHQL_PLAYGROUND: 'true' - # The SDL file is only useful in development (codegen). + # The SDL / OpenAPI files are only useful in development (codegen); the + # document is still served at /api/docs-json. GRAPHQL_SCHEMA_FILE: '' + OPENAPI_FILE: '' depends_on: postgres: { condition: service_healthy } mongo: { condition: service_healthy } @@ -50,6 +60,9 @@ services: postgres: image: postgres:17-alpine + networks: + default: + aliases: [task-stream-postgres] environment: POSTGRES_USER: taskstream POSTGRES_PASSWORD: taskstream @@ -62,6 +75,9 @@ services: mongo: image: mongo:8 + networks: + default: + aliases: [task-stream-mongo] volumes: [mongo-data:/data/db] healthcheck: test: ['CMD', 'mongosh', '--quiet', '--eval', 'db.adminCommand("ping")'] @@ -70,6 +86,9 @@ services: redis: image: redis:7-alpine + networks: + default: + aliases: [task-stream-redis] command: ['redis-server', '--appendonly', 'yes'] volumes: [redis-data:/data] healthcheck: diff --git a/docs/07-despliegue.md b/docs/07-despliegue.md index 58be6c7..e507cc3 100644 --- a/docs/07-despliegue.md +++ b/docs/07-despliegue.md @@ -27,6 +27,15 @@ docker compose down # parar (-v borra los datos) Para probar en local exactamente lo de producción: `docker compose -f docker-compose.yml up -d --build`. +### Nombres únicos en la red + +Los servicios se llaman entre sí por **alias únicos** (`task-stream-api`, `task-stream-postgres`, `task-stream-mongo`, +`task-stream-redis`), no por el nombre del servicio. Al dar dominio a un servicio, Dokploy lo conecta a la red +compartida `dokploy-network`, donde otros proyectos también tienen un `api`, un `postgres` o un `redis`: con nombres +genéricos, el DNS de Docker devuelve también los suyos y nginx reparte las peticiones entre ambos (síntoma: la mitad +de las llamadas a `/api/*` responden `404 Cannot GET …` y el login dice «no configurado»). Si añades un servicio, +dale su alias `task-stream-*` y úsalo en las URLs. + Todos tienen healthcheck; `web` espera a que `api` esté sana, y `api` a las tres bases de datos. ### Imágenes @@ -78,6 +87,8 @@ donde los lee Compose. | `AUTH_SESSION_TTL_SECONDS` | `60` | Cuánto se confía en un token validado antes de volver a preguntar a Pireon | | `GRAPHQL_PLAYGROUND` | `true` | GraphiQL e introspección | | `GRAPHQL_SCHEMA_FILE` | `apps/api/schema.gql` | Dónde escribir el SDL (vacío = no escribir; así está en Docker) | +| `SWAGGER_ENABLED` | `true` | API REST documentada: Swagger UI en `/api/docs`, OpenAPI en `/api/docs-json` | +| `OPENAPI_FILE` | `apps/api/openapi.json` | Dónde escribir el documento OpenAPI al arrancar (vacío = no escribir; así en Docker) | La web no tiene configuración de entorno: llama a la API en su mismo origen (`/api`, `/graphql`). diff --git a/docs/TaskStream-Documentacion.docx b/docs/TaskStream-Documentacion.docx index c3f25c0..8e3b99b 100644 Binary files a/docs/TaskStream-Documentacion.docx and b/docs/TaskStream-Documentacion.docx differ diff --git a/docs/TaskStream-Documentacion.pdf b/docs/TaskStream-Documentacion.pdf index 31d1473..d49d1f3 100644 Binary files a/docs/TaskStream-Documentacion.pdf and b/docs/TaskStream-Documentacion.pdf differ