# 🚀 Customer Portal - Plesk Docker Stack # Deploy via: Plesk → Docker → Stacks → Add Stack # Project name: customer-portal # # Instructions for Plesk Deployment: # 1. Build images locally: # docker build -t portal-frontend:latest -f apps/portal/Dockerfile . # docker build -t portal-backend:latest -f apps/bff/Dockerfile . # 2. Upload images through Plesk → Docker → Images → Upload # 3. Create env files in Plesk private dir: # /var/www/vhosts/asolutions.jp/private/env/portal-frontend.env # /var/www/vhosts/asolutions.jp/private/env/portal-backend.env # 4. Copy this file content to Plesk → Docker → Stacks → Add Stack services: frontend: image: portal-frontend:latest container_name: portal-frontend # Bind to loopback; Plesk nginx will proxy via Proxy Rules ports: - "127.0.0.1:3000:3000" # Only public, client-safe vars env_file: - /var/www/vhosts/asolutions.jp/private/env/portal-frontend.env environment: - PORT=3000 - HOSTNAME=0.0.0.0 restart: unless-stopped depends_on: - backend networks: - portal-network healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"] interval: 30s timeout: 10s start_period: 40s retries: 3 backend: image: portal-backend:latest container_name: portal-backend # Bind to loopback; Plesk nginx will proxy via Proxy Rules ports: - "127.0.0.1:4000:4000" # Ensure name resolution on the default bridge if a custom network can't be created links: - database:database - cache:cache # Secrets and server-side config only env_file: - /var/www/vhosts/asolutions.jp/private/env/portal-backend.env environment: - PORT=4000 volumes: # Mount secrets from Plesk private directory - /var/www/vhosts/asolutions.jp/private/secrets:/app/secrets:ro restart: unless-stopped depends_on: - database - cache networks: - portal-network # Wait for DB, run migrations, then start command: > sh -c " until nc -z database 5432; do echo 'waiting for db'; sleep 2; done; pnpm prisma migrate deploy && node dist/main " healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:4000/health"] interval: 30s timeout: 10s start_period: 60s retries: 3 database: image: postgres:17-alpine container_name: portal-database # No public port exposure; internal only env_file: - /var/www/vhosts/asolutions.jp/private/env/portal-backend.env environment: - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C volumes: - postgres_data:/var/lib/postgresql/data restart: unless-stopped networks: - portal-network healthcheck: test: ["CMD-SHELL", "pg_isready -U portal -d portal_prod"] interval: 10s timeout: 5s retries: 5 start_period: 30s cache: image: redis:7-alpine container_name: portal-cache # No public port exposure; internal only volumes: - redis_data:/data restart: unless-stopped networks: - portal-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 volumes: postgres_data: driver: local redis_data: driver: local networks: portal-network: external: true name: bridge