services: postgres: image: postgres:16-alpine environment: POSTGRES_DB: port_nimara_crm POSTGRES_USER: ${DB_USER:-crm} POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - pgdata:/var/lib/postgresql/data - ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/01-init.sql healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-crm} -d port_nimara_crm"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # build-auditor HIGH: bound memory + log rotation so a stuck query or # noisy log doesn't fill the host disk. Postgres respects shared # buffers env via init.sql; the hard limit here is the container # ceiling. deploy: resources: limits: memory: 2g logging: driver: json-file options: max-size: "20m" max-file: "5" networks: - internal redis: image: redis:7-alpine # BullMQ requires `noeviction` — under memory pressure, allkeys-lru # silently drops queue keys and jobs disappear. See post-audit fix F4. command: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 256mb --maxmemory-policy noeviction volumes: - redisdata:/data healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped deploy: resources: limits: memory: 512m logging: driver: json-file options: max-size: "10m" max-file: "3" networks: - internal crm-app: image: code.letsbe.solutions/letsbe/pn-new-crm/crm-app:latest env_file: .env ports: - "7100:3000" depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: # build-auditor H5: env.PORT is configurable (default 3000), so # template the port into the healthcheck URL. Otherwise overriding # PORT=8080 via .env makes the container healthy-check itself on # the wrong port and enter a restart loop. test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:${PORT:-3000}/api/health"] interval: 15s timeout: 5s retries: 3 # Give the SIGTERM handler in src/server.ts time to drain in-flight # HTTP requests, close Socket.io, and disconnect Redis before Docker # SIGKILLs the process. The internal hard timeout is 25s. stop_grace_period: 30s restart: unless-stopped deploy: resources: limits: memory: 1g logging: driver: json-file options: max-size: "20m" max-file: "5" networks: - internal crm-worker: image: code.letsbe.solutions/letsbe/pn-new-crm/crm-worker:latest env_file: .env depends_on: postgres: condition: service_healthy redis: condition: service_healthy # Match the app: BullMQ jobs need time to finish or be released back # to the queue when worker.ts handles SIGTERM. stop_grace_period: 30s restart: unless-stopped deploy: resources: limits: memory: 1g logging: driver: json-file options: max-size: "20m" max-file: "5" networks: - internal volumes: pgdata: redisdata: networks: internal: driver: bridge