Files
scouthub/docker-compose.yml

214 lines
7.3 KiB
YAML

services:
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "${POSTGRES_PORT}:5432"
volumes:
- scouthub_db_data:/var/lib/postgresql/data
# Crea anche i DB scouthub / scouthub_magazzino / scouthub_eventi
# usati dagli altri backend, sulla stessa istanza (solo al primo init).
- ./db-init:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 10
attivita-backend:
build:
context: ./scouthub-attivita-be
restart: unless-stopped
environment:
PORT: ${ATTIVITA_BACKEND_PORT}
CORS_ORIGIN: http://localhost:${ATTIVITA_FRONTEND_PORT}
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/scouthub?schema=public
KEYCLOAK_BASE_URL: http://keycloak:8080
KEYCLOAK_REALM: scouthub
ports:
- "${ATTIVITA_BACKEND_PORT}:${ATTIVITA_BACKEND_PORT}"
depends_on:
db:
condition: service_healthy
keycloak:
condition: service_started
attivita-frontend:
build:
context: ./scouthub-attivita-fe
args:
API_URL: http://localhost:${ATTIVITA_BACKEND_PORT}
KEYCLOAK_BASE_URL: http://localhost:${KEYCLOAK_PORT}
restart: unless-stopped
ports:
- "${ATTIVITA_FRONTEND_PORT}:80"
depends_on:
- attivita-backend
home-backend:
build:
context: ./scouthub-home-be
restart: unless-stopped
environment:
PORT: ${HOME_BACKEND_PORT}
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public
FRONTEND_BASE_URL: http://localhost:${HOME_FRONTEND_PORT}
# Rete interna Docker: la validazione del JWT (JWKS) non controlla l'issuer,
# quindi non serve che coincida con l'hostname visto dal browser (localhost:8081).
KEYCLOAK_BASE_URL: http://keycloak:8080
KEYCLOAK_REALM: scouthub
KEYCLOAK_ORG_SERVICE_CLIENT_ID: scouthub-home-be
KEYCLOAK_ORG_SERVICE_CLIENT_SECRET: ${KEYCLOAK_ORG_SERVICE_CLIENT_SECRET}
ports:
- "${HOME_BACKEND_PORT}:${HOME_BACKEND_PORT}"
depends_on:
db:
condition: service_healthy
keycloak:
condition: service_started
home-frontend:
build:
context: ./scouthub-home-fe
args:
KEYCLOAK_BASE_URL: http://localhost:${KEYCLOAK_PORT}
ORG_SERVICE_API_BASE_URL: http://localhost:${HOME_BACKEND_PORT}
ATTIVITA_FE_BASE_URL: http://localhost:${ATTIVITA_FRONTEND_PORT}
MAGAZZINO_FE_BASE_URL: http://localhost:${MAGAZZINO_FRONTEND_PORT}
EVENTI_FE_BASE_URL: http://localhost:${EVENTI_FRONTEND_PORT}
restart: unless-stopped
ports:
- "${HOME_FRONTEND_PORT}:80"
depends_on:
- home-backend
magazzino-backend:
build:
context: ./scouthub-magazzino-be
restart: unless-stopped
environment:
PORT: ${MAGAZZINO_BACKEND_PORT}
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/scouthub_magazzino?schema=public
KEYCLOAK_BASE_URL: http://keycloak:8080
KEYCLOAK_REALM: scouthub
KEYCLOAK_MAGAZZINO_CLIENT_ID: scouthub-magazzino-be
KEYCLOAK_MAGAZZINO_CLIENT_SECRET: ${KEYCLOAK_MAGAZZINO_CLIENT_SECRET}
ports:
- "${MAGAZZINO_BACKEND_PORT}:${MAGAZZINO_BACKEND_PORT}"
depends_on:
db:
condition: service_healthy
keycloak:
condition: service_started
magazzino-frontend:
build:
context: ./scouthub-magazzino-fe
args:
KEYCLOAK_BASE_URL: http://localhost:${KEYCLOAK_PORT}
MAGAZZINO_API_BASE_URL: http://localhost:${MAGAZZINO_BACKEND_PORT}
restart: unless-stopped
ports:
- "${MAGAZZINO_FRONTEND_PORT}:80"
depends_on:
- magazzino-backend
eventi-backend:
build:
context: ./scouthub-eventi-be
restart: unless-stopped
environment:
PORT: ${EVENTI_BACKEND_PORT}
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/scouthub_eventi?schema=public
KEYCLOAK_BASE_URL: http://keycloak:8080
KEYCLOAK_REALM: scouthub
KEYCLOAK_EVENTI_CLIENT_ID: scouthub-eventi-be
KEYCLOAK_EVENTI_CLIENT_SECRET: ${KEYCLOAK_EVENTI_CLIENT_SECRET}
KEYCLOAK_AUTHORIZED_SERVICE_CLIENTS: scouthub-eventi-be
ports:
- "${EVENTI_BACKEND_PORT}:${EVENTI_BACKEND_PORT}"
depends_on:
db:
condition: service_healthy
keycloak:
condition: service_started
eventi-frontend:
build:
context: ./scouthub-eventi-fe
args:
KEYCLOAK_BASE_URL: http://localhost:${KEYCLOAK_PORT}
EVENTI_API_BASE_URL: http://localhost:${EVENTI_BACKEND_PORT}
restart: unless-stopped
ports:
- "${EVENTI_FRONTEND_PORT}:80"
depends_on:
- eventi-backend
keycloak-db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
volumes:
- scouthub_keycloak_db_data:/var/lib/postgresql/data
keycloak:
image: quay.io/keycloak/keycloak:26.7
restart: unless-stopped
# --import-realm importa keycloak/realm-export.json solo se il realm non esiste già.
# Le correzioni post-import (ruoli service account, protocol mapper "organization") non
# coperte dal file JSON sono automatizzate dal servizio one-shot "keycloak-init" sotto,
# non più manuali (vedi CLAUDE.md).
command: start-dev --import-realm --health-enabled=true
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://keycloak-db:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
# admin-fine-grained-authz:v1 serve per i permessi granulari sulle Organization (26.7+).
# Verificare con `kc.sh show-config` che i flag richiesti siano invariati nella versione
# effettivamente usata: i nomi dei feature flag cambiano tra minor version di Keycloak.
KC_FEATURES: organization,admin-fine-grained-authz:v1
KC_HOSTNAME: localhost
KC_HOSTNAME_PORT: "${KEYCLOAK_PORT}"
KC_HTTP_ENABLED: "true"
ports:
- "${KEYCLOAK_PORT}:8080"
volumes:
- ./keycloak/realm-export.json:/opt/keycloak/data/import/realm-export.json:ro
- ./keycloak/themes/scouthub:/opt/keycloak/themes/scouthub:ro
depends_on:
- keycloak-db
healthcheck:
test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/9000 && echo -e 'GET /health/ready HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n' >&3 && grep -q '\"status\": \"UP\"' <&3"]
interval: 5s
timeout: 5s
retries: 30
start_period: 30s
keycloak-init:
image: alpine:3.20
restart: "no"
entrypoint: ["sh", "-c", "apk add --no-cache curl jq >/dev/null && sh /init-post-import.sh"]
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
volumes:
- ./keycloak/init-post-import.sh:/init-post-import.sh:ro
depends_on:
keycloak:
condition: service_healthy
volumes:
scouthub_db_data:
scouthub_keycloak_db_data: