version: '3.8' # Stack di produzione per la VPS, pensato per stare dietro a Caddy che gira # su un CT Proxmox separato (routing per path sullo stesso dominio: "/" al # frontend, "/api" al backend, "/auth" a Keycloak - vedi Caddyfile.example). # # Le variabili sono lette da un file ".env" nella stessa cartella # (copia .env.example -> .env e compila i valori prima di avviare lo stack). # # Solo backend, frontend e keycloak pubblicano una porta sull'host (quella # che deve raggiungere Caddy): postgres, mongodb e keycloak-db restano # raggiungibili solo dalla rete Docker interna. services: # PostgreSQL Database (dati app) postgres: image: postgres:15-alpine container_name: scommetti-postgres environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data - ./backend-node/init.sql:/docker-entrypoint-initdb.d/init.sql networks: - scommetti-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # MongoDB Database (bets) mongodb: image: mongo:7 container_name: scommetti-mongodb environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD} MONGO_INITDB_DATABASE: ${MONGO_INITDB_DATABASE} volumes: - mongodb_data:/data/db networks: - scommetti-network healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # Keycloak Database keycloak-db: image: postgres:15-alpine container_name: scommetti-keycloak-db environment: POSTGRES_DB: ${KEYCLOAK_DB} POSTGRES_USER: ${KEYCLOAK_DB_USER} POSTGRES_PASSWORD: ${KEYCLOAK_DB_PASSWORD} volumes: - keycloak_db_data:/var/lib/postgresql/data networks: - scommetti-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${KEYCLOAK_DB_USER} -d ${KEYCLOAK_DB}"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # Keycloak Auth Server keycloak: image: quay.io/keycloak/keycloak:23.0.0 container_name: scommetti-keycloak command: start --import-realm environment: KC_DB: postgres KC_DB_URL: jdbc:postgresql://keycloak-db:5432/${KEYCLOAK_DB} KC_DB_USERNAME: ${KEYCLOAK_DB_USER} KC_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD} KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN} KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD} KC_HEALTH_ENABLED: "true" KC_METRICS_ENABLED: "true" KC_HTTP_ENABLED: "true" # Keycloak รจ raggiunto tramite Caddy su https://${DOMAIN}/auth/*: gli # diciamo di servire tutto sotto /auth e di fidarsi degli header # X-Forwarded-* impostati dal proxy (TLS termina su Caddy, "edge"). KC_HTTP_RELATIVE_PATH: /auth KC_HOSTNAME: ${DOMAIN} KC_HOSTNAME_PATH: /auth KC_HOSTNAME_STRICT: "true" KC_HOSTNAME_STRICT_HTTPS: "true" KC_PROXY: edge ports: - "${BIND_IP}:${KEYCLOAK_PORT}:8080" volumes: - ./keycloak/realm-export.json:/opt/keycloak/data/import/realm.json:ro - ./keycloak/themes/scommettiapp:/opt/keycloak/themes/scommettiapp:ro depends_on: keycloak-db: condition: service_healthy networks: - scommetti-network healthcheck: # Con KC_HTTP_RELATIVE_PATH=/auth l'health endpoint si sposta sotto # /auth/health/ready (verificato: /health/ready da solo risponde 404). test: ["CMD-SHELL", "exec 3<>/dev/tcp/localhost/8080 && printf 'GET /auth/health/ready HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n' >&3 && timeout 5 cat <&3 | grep -q 'UP'"] interval: 15s timeout: 15s retries: 10 start_period: 90s restart: unless-stopped # Backend Node.js backend: build: context: ./backend-node dockerfile: Dockerfile target: production container_name: scommetti-backend environment: NODE_ENV: ${NODE_ENV} PORT: 3000 POSTGRES_URI: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB} MONGO_URI: mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongodb:27017/${MONGO_INITDB_DATABASE}?authSource=admin KEYCLOAK_JWKS_URI: http://keycloak:8080/auth/realms/scommettiapp/protocol/openid-connect/certs ports: - "${BIND_IP}:${BACKEND_PORT}:3000" depends_on: postgres: condition: service_healthy mongodb: condition: service_healthy keycloak: condition: service_healthy networks: - scommetti-network restart: unless-stopped # Frontend Angular (build statica servita da nginx) frontend: build: context: ./frontend-angular dockerfile: Dockerfile target: production container_name: scommetti-frontend ports: - "${BIND_IP}:${FRONTEND_PORT}:80" depends_on: - backend - keycloak networks: - scommetti-network restart: unless-stopped volumes: postgres_data: driver: local mongodb_data: driver: local keycloak_db_data: driver: local networks: scommetti-network: driver: bridge