#!/bin/bash # 启动Docker服务并开始监控 # 用于生产环境的完整启动流程 set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 日志函数 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # 检查Docker和docker-compose是否可用 check_prerequisites() { log_info "检查系统环境..." if ! command -v docker >/dev/null 2>&1; then log_error "Docker未安装或不在PATH中" exit 1 fi if ! command -v docker-compose >/dev/null 2>&1 && ! docker compose version >/dev/null 2>&1; then log_error "docker-compose未安装或不在PATH中" exit 1 fi if ! docker info >/dev/null 2>&1; then log_error "Docker服务未运行或无权限访问" exit 1 fi log_success "系统环境检查通过" } # 创建必要的目录 create_directories() { log_info "创建必要的存储目录..." local dirs=( "./storage/mysql" "./storage/redis" "./storage/meilisearch" "./storage/app" "./storage/app/private/documents" "./storage/app/public" "./storage/logs" "./storage/logs/app" "./storage/logs/queue" ) for dir in "${dirs[@]}"; do if [ ! -d "$dir" ]; then mkdir -p "$dir" log_info "创建目录: $dir" fi done # 设置适当的权限 chmod -R 755 ./storage log_success "存储目录创建完成" } # 检查环境变量配置 check_environment() { log_info "检查环境变量配置..." if [ ! -f ".env" ]; then log_warning ".env文件不存在,将从.env.example创建" if [ -f ".env.example" ]; then cp .env.example .env log_info "已从.env.example创建.env文件,请检查配置" else log_error ".env.example文件不存在,无法创建环境配置" exit 1 fi fi # 检查关键环境变量 local required_vars=("APP_KEY" "DB_PASSWORD") local missing_vars=() for var in "${required_vars[@]}"; do if ! grep -q "^${var}=" .env || grep -q "^${var}=$" .env; then missing_vars+=("$var") fi done if [ ${#missing_vars[@]} -gt 0 ]; then log_warning "以下环境变量未设置或为空:" for var in "${missing_vars[@]}"; do echo " - $var" done log_warning "请在.env文件中设置这些变量" fi log_success "环境变量检查完成" } # 启动服务 start_services() { log_info "启动Docker服务..." # 停止现有服务(如果有) if docker-compose ps -q | grep -q .; then log_info "停止现有服务..." docker-compose down fi # 构建镜像(如果需要) log_info "构建应用镜像..." docker-compose build --no-cache # 启动服务 log_info "启动所有服务..." docker-compose up -d log_success "服务启动命令执行完成" } # 等待服务就绪 wait_for_services() { log_info "等待服务启动完成..." local max_wait=300 # 最大等待时间(秒) local wait_time=0 local check_interval=10 while [ $wait_time -lt $max_wait ]; do log_info "检查服务状态... (${wait_time}/${max_wait}秒)" if ./docker/check-services.sh >/dev/null 2>&1; then log_success "所有服务启动完成并通过健康检查" return 0 fi sleep $check_interval wait_time=$((wait_time + check_interval)) done log_error "服务启动超时,请检查日志" return 1 } # 显示服务状态 show_service_status() { log_info "当前服务状态:" docker-compose ps echo "" log_info "服务访问地址:" echo " Web应用: http://localhost" echo " MySQL: localhost:3306" echo " Redis: localhost:6379" echo " Meilisearch: http://localhost:7700" echo "" log_info "日志查看命令:" echo " 所有服务: docker-compose logs -f" echo " Web应用: docker-compose logs -f app" echo " 队列处理: docker-compose logs -f queue" echo " 数据库: docker-compose logs -f mysql" } # 启动监控 start_monitoring() { log_info "启动服务监控..." # 检查是否已有监控进程在运行 if pgrep -f "monitor-services.sh" >/dev/null; then log_warning "监控进程已在运行,跳过启动" return 0 fi # 在后台启动监控 nohup ./docker/monitor-services.sh > ./storage/logs/monitor-output.log 2>&1 & local monitor_pid=$! echo $monitor_pid > ./storage/logs/monitor.pid log_success "监控进程已启动 (PID: $monitor_pid)" log_info "监控日志文件: ./storage/logs/monitor.log" log_info "监控输出文件: ./storage/logs/monitor-output.log" } # 显示使用帮助 show_help() { echo "Docker服务启动和监控脚本" echo "" echo "用法: $0 [选项]" echo "" echo "选项:" echo " --no-monitor 不启动监控进程" echo " --skip-build 跳过镜像构建" echo " --skip-wait 跳过服务就绪等待" echo " -h, --help 显示此帮助信息" echo "" echo "此脚本将执行以下操作:" echo " 1. 检查系统环境" echo " 2. 创建必要的目录" echo " 3. 检查环境变量配置" echo " 4. 启动Docker服务" echo " 5. 等待服务就绪" echo " 6. 显示服务状态" echo " 7. 启动监控进程" } # 清理函数 cleanup() { log_info "正在清理..." # 停止监控进程 if [ -f "./storage/logs/monitor.pid" ]; then local monitor_pid=$(cat ./storage/logs/monitor.pid) if kill -0 $monitor_pid 2>/dev/null; then log_info "停止监控进程 (PID: $monitor_pid)" kill $monitor_pid fi rm -f ./storage/logs/monitor.pid fi exit 0 } # 设置信号处理 trap cleanup SIGINT SIGTERM # 主函数 main() { local no_monitor=false local skip_build=false local skip_wait=false # 解析命令行参数 while [[ $# -gt 0 ]]; do case $1 in --no-monitor) no_monitor=true shift ;; --skip-build) skip_build=true shift ;; --skip-wait) skip_wait=true shift ;; -h|--help) show_help exit 0 ;; *) echo "未知选项: $1" show_help exit 1 ;; esac done echo "========================================" echo "Docker服务启动和监控" echo "时间: $(date)" echo "========================================" # 执行启动流程 check_prerequisites create_directories check_environment if [ "$skip_build" = false ]; then start_services else log_info "跳过镜像构建,直接启动服务..." docker-compose up -d fi if [ "$skip_wait" = false ]; then wait_for_services else log_warning "跳过服务就绪等待" fi show_service_status if [ "$no_monitor" = false ]; then start_monitoring echo "" log_success "服务启动完成,监控已开始" log_info "使用 Ctrl+C 停止监控并退出" log_info "或使用 'docker-compose down' 停止所有服务" # 等待用户中断 while true; do sleep 60 done else log_success "服务启动完成(未启动监控)" fi } # 如果脚本被直接执行 if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi