x-logging: &default-logging driver: json-file options: { max-size: "10m", max-file: "3" } services: db: image: postgres:16-alpine restart: unless-stopped logging: *default-logging environment: POSTGRES_DB: ${POSTGRES_DB:?required} POSTGRES_USER: ${POSTGRES_USER:?required} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?required} ports: ["5432:5432"] volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] interval: 5s timeout: 5s retries: 10 redis: image: redis:7-alpine restart: unless-stopped logging: *default-logging command: > redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:?required} environment: REDIS_PASSWORD: ${REDIS_PASSWORD} volumes: [redis_data:/data] healthcheck: test: ["CMD-SHELL", "redis-cli --no-auth-warning -a $${REDIS_PASSWORD} ping | grep -q PONG"] interval: 5s timeout: 5s retries: 10 migrate: image: migrate/migrate:v4.17.1 restart: "no" volumes: ["./migrations:/migrations"] depends_on: db: { condition: service_healthy } entrypoint: - migrate - -path=/migrations - -database - postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?sslmode=disable - up auth: build: { context: ./services/auth } restart: unless-stopped logging: *default-logging environment: PORT: 3001 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?sslmode=disable REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379 JWT_SECRET: ${JWT_SECRET:?required} LAMBDAMAIL_MASTER_KEY: ${LAMBDAMAIL_MASTER_KEY:?required} depends_on: db: { condition: service_healthy } redis: { condition: service_healthy } migrate: { condition: service_completed_successfully } healthcheck: test: ["CMD", "node", "-e", "fetch('http://localhost:3001/health/ready').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] interval: 10s timeout: 5s retries: 5 start_period: 15s storage: build: { context: ./services/storage } restart: unless-stopped logging: *default-logging environment: PORT: 3002 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?sslmode=disable REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379 depends_on: db: { condition: service_healthy } redis: { condition: service_healthy } migrate: { condition: service_completed_successfully } healthcheck: test: ["CMD", "node", "-e", "fetch('http://localhost:3002/health/ready').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] interval: 10s timeout: 5s retries: 5 start_period: 15s protocols: build: { context: ./services/protocols } restart: unless-stopped logging: *default-logging ports: ["8080:8080"] environment: DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?sslmode=disable depends_on: db: { condition: service_healthy } migrate: { condition: service_completed_successfully } healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health/ready || exit 1"] interval: 10s timeout: 5s retries: 5 start_period: 15s web: build: { context: ./services/webmail } restart: unless-stopped logging: *default-logging ports: ["3000:3000"] environment: PORT: 3000 AUTH_SERVICE_URL: http://auth:3001 STORAGE_SERVICE_URL: http://storage:3002 depends_on: auth: { condition: service_healthy } storage: { condition: service_healthy } healthcheck: test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3000/health || exit 1"] interval: 10s timeout: 5s retries: 5 start_period: 15s volumes: postgres_data: redis_data: