# Banatie Production - VPS Isolated Deployment # Last Updated: December 2025 services: banatie-api: build: context: /home/usul/workspace/projects/banatie-service dockerfile: apps/api-service/Dockerfile container_name: banatie-api restart: unless-stopped networks: - banatie-internal - proxy-network depends_on: banatie-postgres: condition: service_healthy banatie-minio: condition: service_healthy env_file: - /opt/banatie/.env - /opt/banatie/secrets.env environment: - IS_DOCKER=true - NODE_ENV=production volumes: - /opt/banatie/logs/api:/app/apps/api-service/logs - /opt/banatie/data/api-results:/app/apps/api-service/results - /opt/banatie/data/api-uploads:/app/apps/api-service/uploads healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 60s banatie-landing: build: context: /home/usul/workspace/projects/banatie-service dockerfile: apps/landing/Dockerfile container_name: banatie-landing restart: unless-stopped networks: - banatie-internal - proxy-network depends_on: - banatie-postgres env_file: - /opt/banatie/.env - /opt/banatie/secrets.env environment: - IS_DOCKER=true - NODE_ENV=production - WAITLIST_LOGS_PATH=/app/waitlist-logs - HOSTNAME=0.0.0.0 volumes: - /opt/banatie/data/waitlist-logs:/app/waitlist-logs healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000"] interval: 30s timeout: 10s retries: 3 start_period: 30s banatie-postgres: image: postgres:15-alpine container_name: banatie-postgres restart: unless-stopped networks: - banatie-internal volumes: - /opt/banatie/data/postgres:/var/lib/postgresql/data - /opt/banatie/scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql:ro environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 30s timeout: 10s retries: 3 start_period: 40s banatie-minio: image: quay.io/minio/minio:latest container_name: banatie-minio restart: unless-stopped networks: - banatie-internal - proxy-network volumes: - /opt/banatie/data/minio/drive1:/data1 - /opt/banatie/data/minio/drive2:/data2 - /opt/banatie/data/minio/drive3:/data3 - /opt/banatie/data/minio/drive4:/data4 environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} MINIO_BROWSER_REDIRECT_URL: https://storage.banatie.app MINIO_SERVER_URL: https://cdn.banatie.app command: server /data{1...4} --console-address ":9001" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 10s retries: 3 start_period: 40s banatie-storage-init: image: minio/mc:latest container_name: banatie-storage-init networks: - banatie-internal depends_on: banatie-minio: condition: service_healthy env_file: - /opt/banatie/secrets.env entrypoint: - /bin/sh - -c - | echo '=== MinIO Storage Initialization ===' mc alias set storage http://banatie-minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD} mc mb --ignore-existing storage/banatie mc admin user add storage ${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY} || echo 'User may already exist' mc admin policy attach storage readwrite --user=${MINIO_ACCESS_KEY} || echo 'Policy may already be attached' cat > /tmp/lifecycle.json <<'LCEOF' {"Rules":[{"ID":"temp-cleanup","Status":"Enabled","Filter":{"Prefix":"temp/"},"Expiration":{"Days":7}}]} LCEOF mc ilm import storage/banatie < /tmp/lifecycle.json || echo 'Lifecycle policy may already exist' # Enable public read access for CDN mc anonymous set download storage/banatie || echo 'Anonymous access may already be set' echo 'Public read access enabled for CDN' echo '=== Storage Initialization Completed ===' exit 0 restart: "no" networks: banatie-internal: driver: bridge internal: true proxy-network: name: services_proxy-network external: true