feat: 新增 Docker 部署支持、Swoole/Octane 集成及相关优化
- 添加 Dockerfile 与多套 docker-compose 配置(开发/生产环境) - 集成 Laravel Octane (Swoole) 提升性能 - 新增健康检查、监控脚本及部署文档 - 新增 Docker 镜像离线导入包(MySQL/Redis/Meilisearch) - 优化文档转换、预览服务及队列任务 - 添加 CreateAdminUser 命令与路由健康检查接口 - 新增 Swoole 队列兼容性测试套件 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
616
docker/deploy-to-openeuler.sh
Executable file
616
docker/deploy-to-openeuler.sh
Executable file
@@ -0,0 +1,616 @@
|
||||
#!/bin/bash
|
||||
|
||||
# OpenEuler服务器部署脚本
|
||||
# 用于在OpenEuler服务器上部署Laravel知识库系统
|
||||
|
||||
set -e
|
||||
|
||||
# 脚本配置
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_NAME="knowledge-base"
|
||||
DEPLOY_DIR="/opt/${PROJECT_NAME}"
|
||||
BACKUP_DIR="/opt/${PROJECT_NAME}-backup"
|
||||
LOG_FILE="/var/log/${PROJECT_NAME}-deploy.log"
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log() {
|
||||
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] ✓${NC} $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] ⚠${NC} $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ✗${NC} $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
cat << EOF
|
||||
OpenEuler服务器部署脚本
|
||||
|
||||
用法: $0 [选项] [镜像目录]
|
||||
|
||||
选项:
|
||||
-h, --help 显示此帮助信息
|
||||
-d, --deploy-dir DIR 部署目录 (默认: /opt/knowledge-base)
|
||||
-b, --backup 部署前备份现有安装
|
||||
-u, --update 更新现有部署
|
||||
-r, --rollback 回滚到上一个版本
|
||||
--skip-docker-install 跳过Docker安装
|
||||
--skip-images 跳过镜像导入
|
||||
--skip-env-setup 跳过环境配置
|
||||
--dry-run 仅显示将要执行的操作
|
||||
|
||||
参数:
|
||||
镜像目录 包含Docker镜像文件的目录
|
||||
|
||||
示例:
|
||||
$0 /path/to/docker-images # 全新部署
|
||||
$0 -u /path/to/docker-images # 更新现有部署
|
||||
$0 -b -d /custom/path # 备份并部署到自定义目录
|
||||
$0 --rollback # 回滚到上一个版本
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# 默认配置
|
||||
BACKUP=false
|
||||
UPDATE=false
|
||||
ROLLBACK=false
|
||||
SKIP_DOCKER_INSTALL=false
|
||||
SKIP_IMAGES=false
|
||||
SKIP_ENV_SETUP=false
|
||||
DRY_RUN=false
|
||||
IMAGES_DIR=""
|
||||
|
||||
# 解析命令行参数
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-d|--deploy-dir)
|
||||
DEPLOY_DIR="$2"
|
||||
BACKUP_DIR="${DEPLOY_DIR}-backup"
|
||||
shift 2
|
||||
;;
|
||||
-b|--backup)
|
||||
BACKUP=true
|
||||
shift
|
||||
;;
|
||||
-u|--update)
|
||||
UPDATE=true
|
||||
shift
|
||||
;;
|
||||
-r|--rollback)
|
||||
ROLLBACK=true
|
||||
shift
|
||||
;;
|
||||
--skip-docker-install)
|
||||
SKIP_DOCKER_INSTALL=true
|
||||
shift
|
||||
;;
|
||||
--skip-images)
|
||||
SKIP_IMAGES=true
|
||||
shift
|
||||
;;
|
||||
--skip-env-setup)
|
||||
SKIP_ENV_SETUP=true
|
||||
shift
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
log_error "未知参数: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
IMAGES_DIR="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 检查是否以root权限运行
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
log_error "此脚本需要root权限运行"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建日志目录
|
||||
mkdir -p "$(dirname "$LOG_FILE")"
|
||||
|
||||
log "开始OpenEuler服务器部署..."
|
||||
log "部署目录: $DEPLOY_DIR"
|
||||
log "备份目录: $BACKUP_DIR"
|
||||
log "镜像目录: $IMAGES_DIR"
|
||||
|
||||
# 检查系统信息
|
||||
check_system() {
|
||||
log "检查系统信息..."
|
||||
|
||||
# 检查操作系统
|
||||
if [[ -f /etc/os-release ]]; then
|
||||
source /etc/os-release
|
||||
log "操作系统: $NAME $VERSION"
|
||||
|
||||
if [[ "$ID" != "openEuler" ]] && [[ "$ID_LIKE" != *"rhel"* ]]; then
|
||||
log_warning "此脚本专为OpenEuler设计,当前系统: $NAME"
|
||||
read -p "是否继续? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_warning "无法检测操作系统版本"
|
||||
fi
|
||||
|
||||
# 检查架构
|
||||
local arch=$(uname -m)
|
||||
log "系统架构: $arch"
|
||||
|
||||
if [[ "$arch" != "x86_64" ]]; then
|
||||
log_warning "推荐使用x86_64架构,当前: $arch"
|
||||
fi
|
||||
|
||||
# 检查内存
|
||||
local memory=$(free -h | awk '/^Mem:/ {print $2}')
|
||||
log "系统内存: $memory"
|
||||
|
||||
# 检查磁盘空间
|
||||
local disk_space=$(df -h / | awk 'NR==2 {print $4}')
|
||||
log "可用磁盘空间: $disk_space"
|
||||
}
|
||||
|
||||
# 安装Docker
|
||||
install_docker() {
|
||||
if [[ "$SKIP_DOCKER_INSTALL" == true ]]; then
|
||||
log "跳过Docker安装"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "检查Docker安装状态..."
|
||||
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
local docker_version=$(docker --version)
|
||||
log "Docker已安装: $docker_version"
|
||||
|
||||
# 检查Docker是否运行
|
||||
if systemctl is-active --quiet docker; then
|
||||
log_success "Docker服务正在运行"
|
||||
else
|
||||
log "启动Docker服务..."
|
||||
systemctl start docker
|
||||
systemctl enable docker
|
||||
log_success "Docker服务已启动"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "安装Docker..."
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
log "[DRY RUN] 将安装Docker"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 更新系统包
|
||||
dnf update -y
|
||||
|
||||
# 安装必要的包
|
||||
dnf install -y dnf-plugins-core
|
||||
|
||||
# 添加Docker仓库
|
||||
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
||||
|
||||
# 安装Docker
|
||||
dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
# 启动Docker服务
|
||||
systemctl start docker
|
||||
systemctl enable docker
|
||||
|
||||
# 验证安装
|
||||
if docker --version >/dev/null 2>&1; then
|
||||
log_success "Docker安装成功"
|
||||
else
|
||||
log_error "Docker安装失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 添加当前用户到docker组(如果不是root)
|
||||
if [[ -n "$SUDO_USER" ]]; then
|
||||
usermod -aG docker "$SUDO_USER"
|
||||
log "已将用户 $SUDO_USER 添加到docker组"
|
||||
fi
|
||||
}
|
||||
|
||||
# 安装Docker Compose
|
||||
install_docker_compose() {
|
||||
log "检查Docker Compose..."
|
||||
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
local compose_version=$(docker compose version)
|
||||
log_success "Docker Compose已安装: $compose_version"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "安装Docker Compose..."
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
log "[DRY RUN] 将安装Docker Compose"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Docker Compose通常随Docker一起安装
|
||||
# 如果没有,可以手动安装
|
||||
if ! docker compose version >/dev/null 2>&1; then
|
||||
log_error "Docker Compose未找到,请手动安装"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 备份现有部署
|
||||
backup_existing() {
|
||||
if [[ "$BACKUP" == false ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ ! -d "$DEPLOY_DIR" ]]; then
|
||||
log "没有现有部署需要备份"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "备份现有部署..."
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
log "[DRY RUN] 将备份 $DEPLOY_DIR 到 $BACKUP_DIR"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 停止现有服务
|
||||
if [[ -f "$DEPLOY_DIR/docker-compose.yml" ]]; then
|
||||
log "停止现有服务..."
|
||||
cd "$DEPLOY_DIR"
|
||||
docker compose down || true
|
||||
fi
|
||||
|
||||
# 创建备份
|
||||
local backup_name="${BACKUP_DIR}-$(date +%Y%m%d-%H%M%S)"
|
||||
|
||||
if cp -r "$DEPLOY_DIR" "$backup_name"; then
|
||||
log_success "备份创建成功: $backup_name"
|
||||
|
||||
# 创建符号链接到最新备份
|
||||
rm -f "$BACKUP_DIR"
|
||||
ln -s "$backup_name" "$BACKUP_DIR"
|
||||
else
|
||||
log_error "备份创建失败"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 回滚部署
|
||||
rollback_deployment() {
|
||||
if [[ "$ROLLBACK" == false ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "回滚部署..."
|
||||
|
||||
if [[ ! -L "$BACKUP_DIR" ]] || [[ ! -d "$BACKUP_DIR" ]]; then
|
||||
log_error "没有找到备份,无法回滚"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
log "[DRY RUN] 将从 $BACKUP_DIR 回滚"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 停止当前服务
|
||||
if [[ -f "$DEPLOY_DIR/docker-compose.yml" ]]; then
|
||||
log "停止当前服务..."
|
||||
cd "$DEPLOY_DIR"
|
||||
docker compose down || true
|
||||
fi
|
||||
|
||||
# 恢复备份
|
||||
rm -rf "$DEPLOY_DIR"
|
||||
cp -r "$BACKUP_DIR" "$DEPLOY_DIR"
|
||||
|
||||
# 启动服务
|
||||
cd "$DEPLOY_DIR"
|
||||
docker compose up -d
|
||||
|
||||
log_success "回滚完成"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# 导入Docker镜像
|
||||
import_images() {
|
||||
if [[ "$SKIP_IMAGES" == true ]]; then
|
||||
log "跳过镜像导入"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -z "$IMAGES_DIR" ]] || [[ ! -d "$IMAGES_DIR" ]]; then
|
||||
log_error "镜像目录不存在或未指定: $IMAGES_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "导入Docker镜像..."
|
||||
|
||||
# 查找镜像文件
|
||||
local image_files=($(find "$IMAGES_DIR" -name "*.tar*" -type f))
|
||||
|
||||
if [[ ${#image_files[@]} -eq 0 ]]; then
|
||||
log_error "在 $IMAGES_DIR 中没有找到镜像文件"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "找到 ${#image_files[@]} 个镜像文件"
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
for file in "${image_files[@]}"; do
|
||||
log "[DRY RUN] 将导入: $(basename "$file")"
|
||||
done
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 导入镜像
|
||||
for file in "${image_files[@]}"; do
|
||||
local filename=$(basename "$file")
|
||||
log "导入镜像: $filename"
|
||||
|
||||
if [[ "$file" == *.gz ]]; then
|
||||
# 解压并导入
|
||||
if gunzip -c "$file" | docker load; then
|
||||
log_success "镜像导入成功: $filename"
|
||||
else
|
||||
log_error "镜像导入失败: $filename"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# 直接导入
|
||||
if docker load -i "$file"; then
|
||||
log_success "镜像导入成功: $filename"
|
||||
else
|
||||
log_error "镜像导入失败: $filename"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# 显示导入的镜像
|
||||
log "已导入的镜像:"
|
||||
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
|
||||
}
|
||||
|
||||
# 设置部署环境
|
||||
setup_deployment() {
|
||||
log "设置部署环境..."
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
log "[DRY RUN] 将创建部署目录: $DEPLOY_DIR"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 创建部署目录
|
||||
mkdir -p "$DEPLOY_DIR"
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
# 复制配置文件(如果镜像目录包含)
|
||||
if [[ -n "$IMAGES_DIR" ]]; then
|
||||
# 查找配置文件
|
||||
local config_files=(
|
||||
"docker-compose.yml"
|
||||
".env.production"
|
||||
"docker"
|
||||
)
|
||||
|
||||
for config in "${config_files[@]}"; do
|
||||
if [[ -e "$IMAGES_DIR/../$config" ]]; then
|
||||
log "复制配置: $config"
|
||||
cp -r "$IMAGES_DIR/../$config" .
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# 创建必要的目录
|
||||
mkdir -p storage/{mysql,redis,meilisearch,app,logs}
|
||||
mkdir -p storage/logs/{app,queue}
|
||||
|
||||
# 设置权限
|
||||
chown -R 1000:1000 storage/
|
||||
chmod -R 755 storage/
|
||||
|
||||
log_success "部署环境设置完成"
|
||||
}
|
||||
|
||||
# 配置环境变量
|
||||
setup_environment() {
|
||||
if [[ "$SKIP_ENV_SETUP" == true ]]; then
|
||||
log "跳过环境配置"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "配置环境变量..."
|
||||
|
||||
local env_file="$DEPLOY_DIR/.env"
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
log "[DRY RUN] 将创建环境配置文件: $env_file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 生成随机密钥
|
||||
local app_key="base64:$(openssl rand -base64 32)"
|
||||
local db_password=$(openssl rand -base64 16)
|
||||
local meilisearch_key=$(openssl rand -base64 32)
|
||||
|
||||
# 创建环境配置文件
|
||||
cat > "$env_file" << EOF
|
||||
# Laravel知识库系统 - 生产环境配置
|
||||
# 生成时间: $(date)
|
||||
|
||||
# 应用配置
|
||||
APP_NAME="知识库系统"
|
||||
APP_ENV=production
|
||||
APP_KEY=$app_key
|
||||
APP_DEBUG=false
|
||||
APP_URL=http://localhost
|
||||
|
||||
# 数据库配置
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=mysql
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=knowledge_base
|
||||
DB_USERNAME=knowledge_user
|
||||
DB_PASSWORD=$db_password
|
||||
|
||||
# Redis配置
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=
|
||||
|
||||
# 缓存配置
|
||||
CACHE_STORE=redis
|
||||
SESSION_DRIVER=redis
|
||||
QUEUE_CONNECTION=redis
|
||||
|
||||
# 搜索配置
|
||||
SCOUT_DRIVER=meilisearch
|
||||
MEILISEARCH_HOST=http://meilisearch:7700
|
||||
MEILISEARCH_KEY=$meilisearch_key
|
||||
|
||||
# 日志配置
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=error
|
||||
|
||||
# 文件系统
|
||||
FILESYSTEM_DISK=local
|
||||
|
||||
# 邮件配置
|
||||
MAIL_MAILER=log
|
||||
MAIL_HOST=localhost
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="\${APP_NAME}"
|
||||
EOF
|
||||
|
||||
log_success "环境配置文件创建成功"
|
||||
log_warning "请根据实际情况修改 $env_file 中的配置"
|
||||
}
|
||||
|
||||
# 启动服务
|
||||
start_services() {
|
||||
log "启动服务..."
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
log "[DRY RUN] 将启动Docker Compose服务"
|
||||
return 0
|
||||
fi
|
||||
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
# 检查配置文件
|
||||
if [[ ! -f "docker-compose.yml" ]]; then
|
||||
log_error "docker-compose.yml 文件不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f ".env" ]]; then
|
||||
log_error ".env 文件不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 启动服务
|
||||
if docker compose up -d; then
|
||||
log_success "服务启动成功"
|
||||
else
|
||||
log_error "服务启动失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 等待服务就绪
|
||||
log "等待服务就绪..."
|
||||
sleep 30
|
||||
|
||||
# 检查服务状态
|
||||
docker compose ps
|
||||
|
||||
# 运行Laravel初始化命令
|
||||
log "运行Laravel初始化..."
|
||||
docker compose exec -T app php artisan migrate --force || log_warning "数据库迁移失败"
|
||||
docker compose exec -T app php artisan storage:link || log_warning "存储链接创建失败"
|
||||
|
||||
log_success "部署完成!"
|
||||
}
|
||||
|
||||
# 显示部署信息
|
||||
show_deployment_info() {
|
||||
log "部署信息:"
|
||||
log "部署目录: $DEPLOY_DIR"
|
||||
log "访问地址: http://$(hostname -I | awk '{print $1}')"
|
||||
log "管理命令:"
|
||||
log " 查看日志: cd $DEPLOY_DIR && docker compose logs -f"
|
||||
log " 重启服务: cd $DEPLOY_DIR && docker compose restart"
|
||||
log " 停止服务: cd $DEPLOY_DIR && docker compose down"
|
||||
log " 更新应用: cd $DEPLOY_DIR && docker compose pull && docker compose up -d"
|
||||
}
|
||||
|
||||
# 主执行流程
|
||||
main() {
|
||||
check_system
|
||||
|
||||
# 处理回滚
|
||||
rollback_deployment
|
||||
|
||||
# 备份现有部署
|
||||
backup_existing
|
||||
|
||||
# 安装Docker
|
||||
install_docker
|
||||
install_docker_compose
|
||||
|
||||
# 导入镜像
|
||||
import_images
|
||||
|
||||
# 设置部署环境
|
||||
setup_deployment
|
||||
|
||||
# 配置环境
|
||||
setup_environment
|
||||
|
||||
# 启动服务
|
||||
start_services
|
||||
|
||||
# 显示部署信息
|
||||
show_deployment_info
|
||||
}
|
||||
|
||||
# 执行主流程
|
||||
main
|
||||
Reference in New Issue
Block a user