version: '3.9' networks: harborsmith: driver: bridge volumes: postgres_data: minio_data: keycloak_data: directus_uploads: redis_data: services: # ===== FRONTEND ===== web: build: context: ./apps/web dockerfile: Dockerfile args: - NODE_ENV=production container_name: harborsmith-web restart: unless-stopped ports: - "3000:3000" environment: - NODE_ENV=production - NEXT_PUBLIC_API_URL=http://api:4000 - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL} - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY} - NEXT_PUBLIC_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY} - NEXT_PUBLIC_KEYCLOAK_URL=http://keycloak:8080 - NEXT_PUBLIC_KEYCLOAK_REALM=harborsmith - NEXT_PUBLIC_KEYCLOAK_CLIENT_ID=harborsmith-web depends_on: - api - keycloak networks: - harborsmith # ===== API GATEWAY ===== api: build: context: ./apps/api dockerfile: Dockerfile container_name: harborsmith-api restart: unless-stopped ports: - "4000:4000" environment: - NODE_ENV=production - PORT=4000 - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/harborsmith - REDIS_URL=redis://redis:6379 - KEYCLOAK_URL=http://keycloak:8080 - KEYCLOAK_REALM=harborsmith - KEYCLOAK_CLIENT_ID=harborsmith-api - KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET} - JWT_SECRET=${JWT_SECRET} - CHARTER_SERVICE_URL=http://charter-service:5001 - MAINTENANCE_SERVICE_URL=http://maintenance-service:5002 - PAYMENT_SERVICE_URL=http://payment-service:5003 - NOTIFICATION_SERVICE_URL=http://notification-service:5004 depends_on: - postgres - redis - keycloak networks: - harborsmith # ===== MICROSERVICES ===== charter-service: build: context: ./services/charter dockerfile: Dockerfile container_name: harborsmith-charter restart: unless-stopped ports: - "5001:5001" environment: - NODE_ENV=production - PORT=5001 - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/harborsmith - REDIS_URL=redis://redis:6379 depends_on: - postgres - redis networks: - harborsmith maintenance-service: build: context: ./services/maintenance dockerfile: Dockerfile container_name: harborsmith-maintenance restart: unless-stopped ports: - "5002:5002" environment: - NODE_ENV=production - PORT=5002 - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/harborsmith - REDIS_URL=redis://redis:6379 depends_on: - postgres - redis networks: - harborsmith payment-service: build: context: ./services/payments dockerfile: Dockerfile container_name: harborsmith-payments restart: unless-stopped ports: - "5003:5003" environment: - NODE_ENV=production - PORT=5003 - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY} - STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET} - INVOICE_NINJA_URL=${INVOICE_NINJA_URL} - INVOICE_NINJA_TOKEN=${INVOICE_NINJA_TOKEN} - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/harborsmith depends_on: - postgres networks: - harborsmith notification-service: build: context: ./services/notifications dockerfile: Dockerfile container_name: harborsmith-notifications restart: unless-stopped ports: - "5004:5004" environment: - NODE_ENV=production - PORT=5004 - SMTP_HOST=${POSTE_HOST} - SMTP_PORT=${POSTE_PORT} - SMTP_SECURE=${POSTE_SECURE} - SMTP_USER=${POSTE_USER} - SMTP_PASS=${POSTE_PASS} - LISTMONK_URL=${LISTMONK_URL} - LISTMONK_USER=${LISTMONK_USER} - LISTMONK_PASS=${LISTMONK_PASS} networks: - harborsmith # ===== DATABASES & STORAGE ===== postgres: image: supabase/postgres:15.1.0.117 container_name: harborsmith-db restart: unless-stopped ports: - "5432:5432" environment: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_DB=harborsmith volumes: - postgres_data:/var/lib/postgresql/data - ./migrations:/docker-entrypoint-initdb.d:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 networks: - harborsmith redis: image: redis:7-alpine container_name: harborsmith-redis restart: unless-stopped ports: - "6379:6379" volumes: - redis_data:/data command: redis-server --appendonly yes healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: - harborsmith # ===== AUTHENTICATION ===== keycloak: image: quay.io/keycloak/keycloak:23.0 container_name: harborsmith-keycloak restart: unless-stopped ports: - "8080:8080" environment: - KEYCLOAK_ADMIN=${KEYCLOAK_ADMIN} - KEYCLOAK_ADMIN_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD} - KC_DB=postgres - KC_DB_URL=jdbc:postgresql://postgres:5432/keycloak - KC_DB_USERNAME=postgres - KC_DB_PASSWORD=${POSTGRES_PASSWORD} - KC_HOSTNAME_STRICT=false - KC_HTTP_ENABLED=true - KC_HEALTH_ENABLED=true command: start-dev volumes: - keycloak_data:/opt/keycloak/data depends_on: - postgres networks: - harborsmith # ===== FILE STORAGE ===== minio: image: minio/minio:latest container_name: harborsmith-minio restart: unless-stopped ports: - "9000:9000" - "9001:9001" environment: - MINIO_ROOT_USER=${MINIO_ROOT_USER} - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD} - MINIO_BROWSER_REDIRECT_URL=http://localhost:9001 volumes: - minio_data:/data command: server /data --console-address ":9001" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 networks: - harborsmith createbuckets: image: minio/mc:latest container_name: harborsmith-minio-setup depends_on: - minio entrypoint: > /bin/sh -c " /usr/bin/mc config host add harborsmith http://minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD}; /usr/bin/mc mb harborsmith/documents; /usr/bin/mc mb harborsmith/images; /usr/bin/mc mb harborsmith/directus; /usr/bin/mc policy set public harborsmith/images; exit 0; " networks: - harborsmith # ===== CMS ===== directus: image: directus/directus:10.8 container_name: harborsmith-cms restart: unless-stopped ports: - "8055:8055" environment: - KEY=${DIRECTUS_KEY} - SECRET=${DIRECTUS_SECRET} - DB_CLIENT=pg - DB_HOST=postgres - DB_PORT=5432 - DB_DATABASE=directus - DB_USER=postgres - DB_PASSWORD=${POSTGRES_PASSWORD} - ADMIN_EMAIL=${DIRECTUS_ADMIN_EMAIL} - ADMIN_PASSWORD=${DIRECTUS_ADMIN_PASSWORD} - PUBLIC_URL=http://localhost:8055 - STORAGE_LOCATIONS=s3 - STORAGE_S3_DRIVER=s3 - STORAGE_S3_ENDPOINT=http://minio:9000 - STORAGE_S3_BUCKET=directus - STORAGE_S3_REGION=us-east-1 - STORAGE_S3_KEY=${MINIO_ROOT_USER} - STORAGE_S3_SECRET=${MINIO_ROOT_PASSWORD} volumes: - directus_uploads:/directus/uploads depends_on: - postgres - minio networks: - harborsmith # ===== ANALYTICS ===== umami: image: ghcr.io/umami-software/umami:postgresql-latest container_name: harborsmith-analytics restart: unless-stopped ports: - "3001:3000" environment: - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/umami - DATABASE_TYPE=postgresql - HASH_SALT=${UMAMI_HASH_SALT} - TRACKER_SCRIPT_NAME=script.js - DISABLE_UPDATES=true depends_on: - postgres networks: - harborsmith