# Production Docker Compose for Coolify # Each service should be deployed separately in Coolify # This file is for reference and local testing only version: '3.8' services: # PostgreSQL Database postgres: image: postgres:16-alpine container_name: placebo-postgres restart: unless-stopped environment: POSTGRES_DB: placebo_db POSTGRES_USER: placebo_user POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-placebo_password} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U placebo_user -d placebo_db'] interval: 10s timeout: 5s retries: 5 networks: - placebo-network # Backend API (NestJS) backend: build: context: ./backend dockerfile: Dockerfile container_name: placebo-backend restart: unless-stopped environment: NODE_ENV: production DATABASE_TYPE: postgres DATABASE_HOST: postgres DATABASE_PORT: 5432 DATABASE_USERNAME: placebo_user DATABASE_PASSWORD: ${POSTGRES_PASSWORD:-placebo_password} DATABASE_NAME: placebo_db DATABASE_SYNCHRONIZE: 'false' DATABASE_LOGGING: 'false' JWT_SECRET: ${JWT_SECRET:-change-me-in-production} JWT_EXPIRATION: '86400' CORS_ORIGIN: ${CORS_ORIGIN:-http://localhost:3001} VAPID_SUBJECT: ${VAPID_SUBJECT:-mailto:contact@placebo.mk} VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY} VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY} ports: - '3000:3000' depends_on: postgres: condition: service_healthy healthcheck: test: ['CMD', 'node', '-e', "require('http').get('http://localhost:3000/health', (r) => {if(r.statusCode !== 200) process.exit(1)})"] interval: 30s timeout: 10s retries: 3 start_period: 40s networks: - placebo-network # Frontend (React) frontend: build: context: ./frontend dockerfile: Dockerfile args: VITE_API_URL: ${VITE_API_URL:-http://localhost:3000/api/v1} VITE_CMS_URL: ${VITE_CMS_URL:-http://localhost:1337} container_name: placebo-frontend restart: unless-stopped ports: - '3001:80' depends_on: - backend healthcheck: test: ['CMD', 'wget', '--no-verbose', '--tries=1', '--spider', 'http://localhost:80/'] interval: 30s timeout: 10s retries: 3 networks: - placebo-network # PWA (Progressive Web App) pwa: build: context: ./pwa dockerfile: Dockerfile args: VITE_API_URL: ${VITE_API_URL:-http://localhost:3000/api/v1} VITE_CMS_URL: ${VITE_CMS_URL:-http://localhost:1337} container_name: placebo-pwa restart: unless-stopped ports: - '5174:80' depends_on: - backend healthcheck: test: ['CMD', 'wget', '--no-verbose', '--tries=1', '--spider', 'http://localhost:80/'] interval: 30s timeout: 10s retries: 3 networks: - placebo-network # CMS (Strapi) cms: build: context: ./cms/cms dockerfile: Dockerfile container_name: placebo-cms restart: unless-stopped environment: NODE_ENV: production DATABASE_CLIENT: postgres DATABASE_HOST: postgres DATABASE_PORT: 5432 DATABASE_NAME: placebo_cms_db DATABASE_USERNAME: placebo_user DATABASE_PASSWORD: ${POSTGRES_PASSWORD:-placebo_password} DATABASE_SSL: 'false' HOST: 0.0.0.0 PORT: 1337 APP_KEYS: ${STRAPI_APP_KEYS:-key1,key2,key3,key4} API_TOKEN_SALT: ${STRAPI_API_TOKEN_SALT:-change-me} ADMIN_JWT_SECRET: ${STRAPI_ADMIN_JWT_SECRET:-change-me} TRANSFER_TOKEN_SALT: ${STRAPI_TRANSFER_TOKEN_SALT:-change-me} JWT_SECRET: ${STRAPI_JWT_SECRET:-change-me} ports: - '1337:1337' depends_on: postgres: condition: service_healthy volumes: - cms_uploads:/app/public/uploads healthcheck: test: ['CMD', 'node', '-e', "require('http').get('http://localhost:1337/_health', (r) => {if(r.statusCode !== 200) process.exit(1)})"] interval: 30s timeout: 10s retries: 3 start_period: 60s networks: - placebo-network volumes: postgres_data: driver: local cms_uploads: driver: local networks: placebo-network: driver: bridge