#!/bin/bash # ================================================ # Math Platform - Production Start Script # ================================================ set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DOCKER_COMPOSE_FILE="$PROJECT_ROOT/docker-compose.yml" BACKUP_DIR="$PROJECT_ROOT/docker/backups" LOG_DIR="$PROJECT_ROOT/docker/logs" echo -e "${BLUE}============================================${NC}" echo -e "${BLUE}Math Platform - Production Start${NC}" echo -e "${BLUE}============================================${NC}" # Create necessary directories mkdir -p "$BACKUP_DIR" mkdir -p "$LOG_DIR" mkdir -p "$PROJECT_ROOT/pdfs/processed" # Check if .env exists if [ ! -f "$PROJECT_ROOT/.env" ]; then echo -e "${RED}Error: .env file not found!${NC}" echo -e "${YELLOW}Please copy .env.example to .env and configure it.${NC}" exit 1 fi # Function to check if Docker is running check_docker() { if ! docker info > /dev/null 2>&1; then echo -e "${RED}Error: Docker is not running!${NC}" exit 1 fi echo -e "${GREEN}Docker is running${NC}" } # Function to check if docker-compose is available check_docker_compose() { if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then echo -e "${RED}Error: docker-compose not found!${NC}" exit 1 fi echo -e "${GREEN}Docker Compose is available${NC}" } # Function to backup database before starting backup_database() { echo -e "${YELLOW}Creating database backup before starting...${NC}" TIMESTAMP=$(date +%Y%m%d_%H%M%S) BACKUP_FILE="$BACKUP_DIR/mathdb_backup_$TIMESTAMP.sql" if docker ps | grep -q math-postgres; then docker exec math-postgres pg_dump -U mathuser mathdb > "$BACKUP_FILE" 2>/dev/null || true if [ -f "$BACKUP_FILE" ] && [ -s "$BACKUP_FILE" ]; then echo -e "${GREEN}Backup created: $BACKUP_FILE${NC}" gzip "$BACKUP_FILE" else echo -e "${YELLOW}No existing database to backup (first run)${NC}" fi else echo -e "${YELLOW}Database container not running (first run)${NC}" fi } # Function to pull latest images pull_images() { echo -e "${YELLOW}Pulling latest Docker images...${NC}" docker-compose -f "$DOCKER_COMPOSE_FILE" pull } # Function to build images build_images() { echo -e "${YELLOW}Building Docker images...${NC}" docker-compose -f "$DOCKER_COMPOSE_FILE" build --no-cache } # Function to start services start_services() { echo -e "${YELLOW}Starting services...${NC}" docker-compose -f "$DOCKER_COMPOSE_FILE" up -d echo -e "${GREEN}Services started successfully!${NC}" } # Function to wait for services to be healthy wait_for_services() { echo -e "${YELLOW}Waiting for services to be healthy...${NC}" # Wait for PostgreSQL echo -n "Waiting for PostgreSQL..." timeout=60 while [ $timeout -gt 0 ]; do if docker exec math-postgres pg_isready -U mathuser -d mathdb &> /dev/null; then echo -e " ${GREEN}OK${NC}" break fi echo -n "." sleep 2 timeout=$((timeout-2)) done if [ $timeout -le 0 ]; then echo -e " ${RED}FAILED${NC}" return 1 fi # Wait for Backend echo -n "Waiting for Backend..." timeout=90 while [ $timeout -gt 0 ]; do if docker exec math-backend wget -q -O /dev/null http://localhost:3001/health 2>/dev/null; then echo -e " ${GREEN}OK${NC}" break fi echo -n "." sleep 2 timeout=$((timeout-2)) done if [ $timeout -le 0 ]; then echo -e " ${YELLOW}TAKING LONGER THAN EXPECTED${NC}" fi # Wait for Frontend echo -n "Waiting for Frontend..." timeout=90 while [ $timeout -gt 0 ]; do if docker exec math-frontend wget -q -O /dev/null http://localhost:3000 2>/dev/null; then echo -e " ${GREEN}OK${NC}" break fi echo -n "." sleep 2 timeout=$((timeout-2)) done if [ $timeout -le 0 ]; then echo -e " ${YELLOW}TAKING LONGER THAN EXPECTED${NC}" fi } # Function to run database migrations run_migrations() { echo -e "${YELLOW}Running database migrations...${NC}" docker-compose -f "$DOCKER_COMPOSE_FILE" exec -T backend npx prisma migrate deploy || { echo -e "${YELLOW}Migration failed or already applied${NC}" } } # Function to show service status show_status() { echo -e "\n${BLUE}============================================${NC}" echo -e "${BLUE}Service Status${NC}" echo -e "${BLUE}============================================${NC}" docker-compose -f "$DOCKER_COMPOSE_FILE" ps echo -e "\n${BLUE}============================================${NC}" echo -e "${BLUE}Access Information${NC}" echo -e "${BLUE}============================================${NC}" echo -e "${GREEN}Frontend:${NC} http://localhost:3000" echo -e "${GREEN}Backend:${NC} http://localhost:3001" echo -e "${GREEN}Nginx:${NC} http://localhost:80" echo -e "\n${YELLOW}View logs with: docker-compose logs -f [service_name]${NC}" echo -e "${YELLOW}Stop services with: ./docker/stop.sh${NC}" } # Main execution main() { check_docker check_docker_compose backup_database # Parse arguments REBUILD=false PULL=false while [[ $# -gt 0 ]]; do case $1 in --rebuild) REBUILD=true shift ;; --pull) PULL=true shift ;; *) echo -e "${RED}Unknown option: $1${NC}" echo "Usage: $0 [--rebuild] [--pull]" exit 1 ;; esac done if [ "$PULL" = true ]; then pull_images fi if [ "$REBUILD" = true ]; then build_images fi start_services sleep 5 wait_for_services run_migrations show_status echo -e "\n${GREEN}Math Platform started successfully!${NC}" } # Run main function main "$@"