Files
goodgo-platform/docker-compose.yml
Ho Ngoc Hai 25420720e7 fix(api,ci): remove type-only imports for DI and isolate CI ports from dev
- Remove `type` keyword from NestJS injectable class imports across all
  modules to fix runtime DI resolution (330+ handler/listener files)
- Offset CI docker-compose ports (5433/6380/8109/9002) to avoid
  conflicts with running dev containers
- Update .env.test, playwright.config.ts, and e2e workflow to use
  isolated CI ports with configurable overrides
- Fix prisma/seed.ts to use deterministic IDs for Prisma 7 upsert
  compatibility (phoneHash replaced phone as unique index)
- Add dedicated Docker bridge network for CI service containers

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
2026-04-13 01:40:14 +07:00

270 lines
7.5 KiB
YAML

services:
postgres:
image: postgis/postgis:16-3.4
container_name: goodgo-postgres
restart: unless-stopped
ports:
- '${DB_PORT:-5432}:5432'
environment:
POSTGRES_DB: ${DB_NAME:-goodgo}
POSTGRES_USER: ${DB_USER:-goodgo}
POSTGRES_PASSWORD: ${DB_PASSWORD:-goodgo_secret}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U ${DB_USER:-goodgo} -d ${DB_NAME:-goodgo}']
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- goodgo-net
redis:
image: redis:7-alpine
container_name: goodgo-redis
restart: unless-stopped
ports:
- '${REDIS_PORT:-6379}:6379'
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
- goodgo-net
typesense:
image: typesense/typesense:27.1
container_name: goodgo-typesense
restart: unless-stopped
ports:
- '${TYPESENSE_PORT:-8108}:8108'
environment:
TYPESENSE_API_KEY: ${TYPESENSE_API_KEY:-ts_dev_key_change_me}
TYPESENSE_DATA_DIR: /data
TYPESENSE_ENABLE_CORS: 'true'
volumes:
- typesense_data:/data
healthcheck:
test: ['CMD-SHELL', 'bash -c "echo > /dev/tcp/localhost/8108"']
interval: 10s
timeout: 5s
retries: 5
start_period: 15s
networks:
- goodgo-net
minio:
image: minio/minio:latest
container_name: goodgo-minio
restart: unless-stopped
ports:
- '${MINIO_API_PORT:-9000}:9000'
- '${MINIO_CONSOLE_PORT:-9001}:9001'
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:?MINIO_ACCESS_KEY is required}
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:?MINIO_SECRET_KEY is required}
volumes:
- minio_data:/data
healthcheck:
test: ['CMD', 'mc', 'ready', 'local']
interval: 10s
timeout: 5s
retries: 5
start_period: 15s
networks:
- goodgo-net
ai-services:
build:
context: ./libs/ai-services
dockerfile: Dockerfile
container_name: goodgo-ai-services
restart: unless-stopped
ports:
- '${AI_SERVICES_PORT:-8000}:8000'
environment:
AI_DEBUG: ${AI_DEBUG:-false}
AI_LOG_LEVEL: ${AI_LOG_LEVEL:-info}
healthcheck:
test: ['CMD', 'python', '-c', 'import httpx; httpx.get("http://localhost:8000/health").raise_for_status()']
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
networks:
- goodgo-net
# ── Database Backup ──
pg-backup:
image: postgis/postgis:16-3.4
container_name: goodgo-pg-backup
restart: unless-stopped
entrypoint: /bin/bash
command:
- -c
- |
apt-get update -qq && apt-get install -y -qq cron > /dev/null 2>&1
(echo "0 2 * * * PGHOST=postgres PGPORT=5432 PGUSER=${DB_USER:-goodgo} PGDATABASE=${DB_NAME:-goodgo} PGPASSWORD=${DB_PASSWORD:-goodgo_secret} BACKUP_DIR=/backups RETENTION_DAYS=${BACKUP_RETENTION_DAYS:-7} /scripts/pg-backup.sh >> /var/log/pg-backup.log 2>&1"; echo "0 4 * * * PGHOST=postgres PGPORT=5432 PGUSER=${DB_USER:-goodgo} PGDATABASE=${DB_NAME:-goodgo} PGPASSWORD=${DB_PASSWORD:-goodgo_secret} BACKUP_DIR=/backups REPORT_FILE=/backups/verify-latest.json /scripts/pg-verify-backup.sh >> /var/log/pg-verify-backup.log 2>&1") | crontab -
/scripts/pg-backup.sh
cron -f
environment:
PGHOST: postgres
PGPORT: '5432'
PGUSER: ${DB_USER:-goodgo}
PGDATABASE: ${DB_NAME:-goodgo}
PGPASSWORD: ${DB_PASSWORD:-goodgo_secret}
BACKUP_DIR: /backups
RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-7}
volumes:
- ./scripts/backup:/scripts:ro
- pg_backups:/backups
depends_on:
postgres:
condition: service_healthy
networks:
- goodgo-net
# ── Backup Verification (on-demand) ──
# Run manually: docker compose run --rm pg-verify-backup
pg-verify-backup:
image: postgis/postgis:16-3.4
container_name: goodgo-pg-verify-backup
profiles:
- tools
entrypoint: /bin/bash
command:
- -c
- /scripts/pg-verify-backup.sh
environment:
PGHOST: postgres
PGPORT: '5432'
PGUSER: ${DB_USER:-goodgo}
PGDATABASE: ${DB_NAME:-goodgo}
PGPASSWORD: ${DB_PASSWORD:-goodgo_secret}
BACKUP_DIR: /backups
REPORT_FILE: /backups/verify-report.json
volumes:
- ./scripts/backup:/scripts:ro
- pg_backups:/backups
depends_on:
postgres:
condition: service_healthy
networks:
- goodgo-net
# ── Log Aggregation ──
loki:
image: grafana/loki:3.0.0
container_name: goodgo-loki
restart: unless-stopped
ports:
- '${LOKI_PORT:-3100}:3100'
command: -config.file=/etc/loki/loki-config.yml
volumes:
- ./monitoring/loki/loki-config.yml:/etc/loki/loki-config.yml:ro
- loki_data:/loki
healthcheck:
test: ['CMD', 'wget', '--spider', '-q', 'http://localhost:3100/ready']
interval: 15s
timeout: 5s
retries: 5
start_period: 20s
networks:
- goodgo-net
promtail:
image: grafana/promtail:3.0.0
container_name: goodgo-promtail
restart: unless-stopped
command: -config.file=/etc/promtail/promtail-config.yml
volumes:
- ./monitoring/promtail/promtail-config.yml:/etc/promtail/promtail-config.yml:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
loki:
condition: service_healthy
networks:
- goodgo-net
prometheus:
image: prom/prometheus:v2.51.0
container_name: goodgo-prometheus
restart: unless-stopped
ports:
- '${PROMETHEUS_PORT:-9090}:9090'
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=15d'
- '--web.enable-lifecycle'
volumes:
- ./monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
extra_hosts:
- 'host.docker.internal:host-gateway'
healthcheck:
test: ['CMD', 'wget', '--spider', '-q', 'http://localhost:9090/-/healthy']
interval: 15s
timeout: 5s
retries: 3
start_period: 10s
networks:
- goodgo-net
grafana:
image: grafana/grafana:10.4.1
container_name: goodgo-grafana
restart: unless-stopped
ports:
- '${GRAFANA_PORT:-3002}:3000'
environment:
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:-admin}
GF_USERS_ALLOW_SIGN_UP: 'false'
volumes:
- ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro
- ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro
- grafana_data:/var/lib/grafana
depends_on:
prometheus:
condition: service_healthy
loki:
condition: service_healthy
healthcheck:
test: ['CMD', 'wget', '--spider', '-q', 'http://localhost:3000/api/health']
interval: 15s
timeout: 5s
retries: 3
start_period: 15s
networks:
- goodgo-net
volumes:
pgdata:
driver: local
redis_data:
driver: local
typesense_data:
driver: local
minio_data:
driver: local
pg_backups:
driver: local
loki_data:
driver: local
prometheus_data:
driver: local
grafana_data:
driver: local
networks:
goodgo-net:
driver: bridge
name: goodgo-net