# TimeSafari Docker Compose Configuration # Author: Matthew Raymer # Description: Multi-environment Docker Compose setup for TimeSafari # # IMPORTANT: Build web assets first using npm scripts before running docker-compose # # Usage: # Development: npm run build:web:build -- --mode development && docker-compose up dev # Test: npm run build:web:build -- --mode test && docker-compose up test # Production: npm run build:web:build -- --mode production && docker-compose up production # Custom: BUILD_MODE=test npm run build:web:build -- --mode test && docker-compose up custom # # Environment Variables: # BUILD_MODE: development, test, or production (default: production) # NODE_ENV: node environment (default: production) # PORT: port to expose (default: 80 for production, 8080 for test) # ENV_FILE: environment file to use (default: .env.production) # # Note: For development, use npm run build:web directly (no Docker needed) version: '3.8' # Default values that can be overridden x-defaults: &defaults build: context: . dockerfile: Dockerfile args: BUILD_MODE: ${BUILD_MODE:-production} NODE_ENV: ${NODE_ENV:-production} restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s services: # Test service for testing environment test: <<: *defaults build: context: . dockerfile: Dockerfile target: test args: BUILD_MODE: test NODE_ENV: test ports: - "${TEST_PORT:-8080}:80" environment: - NODE_ENV=test - BUILD_MODE=test env_file: - ${TEST_ENV_FILE:-.env.test} # Production service production: <<: *defaults build: context: . dockerfile: Dockerfile target: production args: BUILD_MODE: production NODE_ENV: production ports: - "${PROD_PORT:-80}:80" environment: - NODE_ENV=production - BUILD_MODE=production env_file: - ${PROD_ENV_FILE:-.env.production} # Production service with SSL (requires certificates) production-ssl: <<: *defaults build: context: . dockerfile: Dockerfile target: production args: BUILD_MODE: production NODE_ENV: production ports: - "${SSL_PORT:-443}:443" - "${HTTP_PORT:-80}:80" environment: - NODE_ENV=production - BUILD_MODE=production env_file: - ${PROD_ENV_FILE:-.env.production} volumes: - ./ssl:/etc/nginx/ssl:ro - ./docker/nginx-ssl.conf:/etc/nginx/conf.d/default.conf:ro healthcheck: test: ["CMD", "curl", "-f", "https://localhost/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # Custom service - configurable via environment variables custom: <<: *defaults build: context: . dockerfile: Dockerfile target: ${BUILD_TARGET:-production} args: BUILD_MODE: ${BUILD_MODE:-production} NODE_ENV: ${NODE_ENV:-production} ports: - "${CUSTOM_PORT:-8080}:${CUSTOM_INTERNAL_PORT:-80}" environment: - NODE_ENV=${NODE_ENV:-production} - BUILD_MODE=${BUILD_MODE:-production} env_file: - ${CUSTOM_ENV_FILE:-.env.production} healthcheck: test: ["CMD", "curl", "-f", "http://localhost:${CUSTOM_INTERNAL_PORT:-80}/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # Load balancer for production (optional) nginx-lb: image: nginx:alpine ports: - "${LB_PORT:-80}:80" - "${LB_SSL_PORT:-443}:443" volumes: - ./docker/nginx-lb.conf:/etc/nginx/nginx.conf:ro - ./ssl:/etc/nginx/ssl:ro depends_on: - production restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s networks: default: driver: bridge ipam: config: - subnet: 172.20.0.0/16