version: '3.8' services: # PostgreSQL Database postgres: image: postgres:16-alpine container_name: taskflow-db restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-taskflow} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-taskflow_password} POSTGRES_DB: ${POSTGRES_DB:-taskflow} volumes: - postgres_data:/var/lib/postgresql/data ports: - "${POSTGRES_PORT:-2101}:5432" healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-taskflow}" ] interval: 10s timeout: 5s retries: 5 networks: - taskflow-network # TaskFlow Application app: build: context: . dockerfile: Dockerfile target: production container_name: taskflow-app restart: unless-stopped environment: NODE_ENV: production DATABASE_URL: postgresql://${POSTGRES_USER:-taskflow}:${POSTGRES_PASSWORD:-taskflow_password}@postgres:5432/${POSTGRES_DB:-taskflow} PORT: 5000 # DATABASE_SSL options: 'true' (SSL with self-signed), 'require' (SSL with valid cert), or unset (no SSL) # For local postgres container, leave unset. For external PostgreSQL, set as needed. DATABASE_SSL: ${DATABASE_SSL:-} SESSION_SECRET: ${SESSION_SECRET:-supersecret_session_key} SMTP_HOST: mailhog SMTP_PORT: 1025 SMTP_SECURE: false # volumes: # - ./dist/public:/app/server/public ports: - "2100:5000" depends_on: postgres: condition: service_healthy healthcheck: test: [ "CMD", "node", "-e", "require('http').get('http://localhost:5000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" ] interval: 30s timeout: 10s retries: 3 start_period: 40s networks: - taskflow-network # MailHog - Local SMTP Server mailhog: image: mailhog/mailhog container_name: taskflow-mailhog ports: - "2102:1025" # SMTP - "2103:8025" # Web UI networks: - taskflow-network volumes: postgres_data: driver: local networks: taskflow-network: driver: bridge