services: # Traefik - Reverse Proxy traefik: image: traefik:v3.2 container_name: aggios-traefik restart: unless-stopped command: - "--api.insecure=true" - "--providers.file.directory=/etc/traefik/dynamic" - "--providers.file.watch=true" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--log.level=DEBUG" - "--accesslog=true" ports: - "80:80" - "443:443" - "8080:8080" # Dashboard Traefik volumes: - ./traefik/dynamic:/etc/traefik/dynamic:ro networks: - aggios-network # PostgreSQL Database postgres: image: postgres:16-alpine container_name: aggios-postgres restart: unless-stopped ports: - "5432:5432" environment: POSTGRES_USER: aggios POSTGRES_PASSWORD: ${DB_PASSWORD:-A9g10s_S3cur3_P@ssw0rd_2025!} POSTGRES_DB: aggios_db volumes: - postgres_data:/var/lib/postgresql/data - ./backend/internal/data/postgres/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql healthcheck: test: [ "CMD-SHELL", "pg_isready -U aggios -d aggios_db" ] interval: 10s timeout: 5s retries: 5 networks: - aggios-network # Redis Cache redis: image: redis:7-alpine container_name: aggios-redis restart: unless-stopped command: redis-server --requirepass ${REDIS_PASSWORD:-R3d1s_S3cur3_P@ss_2025!} volumes: - redis_data:/data healthcheck: test: [ "CMD", "redis-cli", "ping" ] interval: 10s timeout: 5s retries: 5 networks: - aggios-network # MinIO Object Storage minio: image: minio/minio:RELEASE.2024-01-31T20-20-33Z container_name: aggios-minio restart: unless-stopped command: server /data --console-address ":9001" labels: - "traefik.enable=true" # Router para acesso aos arquivos (API S3) - "traefik.http.routers.minio.rule=Host(`files.aggios.local`) || Host(`files.localhost`)" - "traefik.http.routers.minio.entrypoints=web" - "traefik.http.routers.minio.priority=100" # Prioridade alta para evitar captura pelo wildcard - "traefik.http.services.minio.loadbalancer.server.port=9000" - "traefik.http.services.minio.loadbalancer.passhostheader=true" # Router para o Console do MinIO - "traefik.http.routers.minio-console.rule=Host(`minio.aggios.local`) || Host(`minio.localhost`)" - "traefik.http.routers.minio-console.entrypoints=web" - "traefik.http.routers.minio-console.priority=100" - "traefik.http.services.minio-console.loadbalancer.server.port=9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: ${MINIO_PASSWORD:-M1n10_S3cur3_P@ss_2025!} MINIO_BROWSER_REDIRECT_URL: http://minio.localhost MINIO_SERVER_URL: http://files.localhost volumes: - minio_data:/data ports: - "9000:9000" - "9001:9001" healthcheck: test: [ "CMD-SHELL", "timeout 5 bash -c ':> /dev/tcp/127.0.0.1/9000' || exit 1" ] interval: 10s timeout: 5s retries: 5 start_period: 10s networks: - aggios-network # Go Backend API backend: build: context: ./backend dockerfile: Dockerfile container_name: aggios-backend restart: unless-stopped ports: - "8085:8080" labels: - "traefik.enable=true" - "traefik.http.routers.backend.rule=Host(`api.aggios.local`) || Host(`api.localhost`)" - "traefik.http.routers.backend.entrypoints=web" - "traefik.http.services.backend.loadbalancer.server.port=8080" environment: TZ: America/Sao_Paulo SERVER_HOST: 0.0.0.0 SERVER_PORT: 8080 JWT_SECRET: ${JWT_SECRET:-Th1s_1s_A_V3ry_S3cur3_JWT_S3cr3t_K3y_2025_Ch@ng3_In_Pr0d!} DB_HOST: postgres DB_PORT: 5432 DB_USER: aggios DB_PASSWORD: ${DB_PASSWORD:-A9g10s_S3cur3_P@ssw0rd_2025!} DB_NAME: aggios_db REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-R3d1s_S3cur3_P@ss_2025!} MINIO_ENDPOINT: minio:9000 MINIO_PUBLIC_URL: http://files.localhost MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: ${MINIO_PASSWORD:-M1n10_S3cur3_P@ss_2025!} volumes: - ./backups:/backups depends_on: postgres: condition: service_healthy redis: condition: service_healthy minio: condition: service_healthy networks: - aggios-network # Frontend - Institucional (aggios.app) institucional: build: context: ./frontend-aggios.app dockerfile: Dockerfile container_name: aggios-institucional restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.institucional.rule=Host(`aggios.local`) || Host(`localhost`)" - "traefik.http.routers.institucional.entrypoints=web" - "traefik.http.services.institucional.loadbalancer.server.port=3000" environment: - NODE_ENV=production - NEXT_PUBLIC_API_URL=http://api.localhost healthcheck: test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000" ] interval: 30s timeout: 10s retries: 3 start_period: 40s networks: - aggios-network # Frontend - Dashboard (dash.aggios.app) dashboard: build: context: ./front-end-dash.aggios.app dockerfile: Dockerfile container_name: aggios-dashboard restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.dashboard.rule=Host(`dash.aggios.local`) || Host(`dash.localhost`)" - "traefik.http.routers.dashboard.entrypoints=web" - "traefik.http.services.dashboard.loadbalancer.server.port=3000" environment: - NODE_ENV=production - NEXT_PUBLIC_API_URL=http://api.localhost healthcheck: test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000" ] interval: 30s timeout: 10s retries: 3 start_period: 40s networks: - aggios-network # Frontend - Agency (tenant-only) agency: build: context: ./front-end-agency dockerfile: Dockerfile container_name: aggios-agency restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.agency.rule=Host(`agency.aggios.local`) || Host(`agency.localhost`) || HostRegexp(`^.+\\.localhost$`)" - "traefik.http.routers.agency.entrypoints=web" - "traefik.http.routers.agency.priority=1" # Prioridade baixa para não conflitar com files/minio environment: - NODE_ENV=production - NEXT_PUBLIC_API_URL=http://api.localhost - API_INTERNAL_URL=http://backend:8080 healthcheck: test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000" ] interval: 30s timeout: 10s retries: 3 start_period: 40s networks: - aggios-network volumes: postgres_data: driver: local redis_data: driver: local minio_data: driver: local networks: aggios-network: driver: bridge