Files
KnowledgeBase/deploy.sh
lizhuoran 3c206e9e06 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>
2026-02-28 15:51:19 +08:00

284 lines
7.8 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 知识库系统部署脚本
# 使用Laravel Octane + Swoole
set -e # 遇到错误立即退出
# 配置变量
SERVER_HOST="192.168.1.33"
SERVER_USER="root"
SERVER_PASSWORD="Sipai@123"
SERVER_PATH="/opt/KnowledgeBase"
IMAGE_NAME="knowledge-base-app"
IMAGE_TAG="latest"
COMPOSE_VERSION="1.25.5"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查必要工具
check_requirements() {
log_info "检查部署环境..."
if ! command -v docker &> /dev/null; then
log_error "Docker 未安装"
exit 1
fi
if ! command -v sshpass &> /dev/null; then
log_error "sshpass 未安装,请先安装: brew install sshpass"
exit 1
fi
log_info "环境检查完成"
}
# 设置网络代理(如果需要)
setup_proxy() {
if [ "$USE_PROXY" = "true" ]; then
log_info "设置网络代理..."
export https_proxy=http://127.0.0.1:7890
export http_proxy=http://127.0.0.1:7890
export all_proxy=socks5://127.0.0.1:7890
log_info "代理设置完成"
fi
}
# 清理本地构建文件
clean_local() {
log_info "清理本地构建文件..."
# 清理不需要的文件
rm -rf node_modules/.cache
rm -rf storage/logs/*.log
rm -rf storage/framework/cache/data/*
rm -rf storage/framework/sessions/*
rm -rf storage/framework/views/*
log_info "本地清理完成"
}
# 构建Docker镜像
build_image() {
log_info "开始构建Docker镜像..."
# 构建镜像
docker build --platform linux/amd64 -t ${IMAGE_NAME}:${IMAGE_TAG} .
if [ $? -eq 0 ]; then
log_info "Docker镜像构建成功"
else
log_error "Docker镜像构建失败"
exit 1
fi
}
# 导出镜像为tar包
export_image() {
log_info "导出Docker镜像..."
docker save ${IMAGE_NAME}:${IMAGE_TAG} | gzip > ${IMAGE_NAME}-${IMAGE_TAG}.tar.gz
if [ $? -eq 0 ]; then
log_info "镜像导出成功: ${IMAGE_NAME}-${IMAGE_TAG}.tar.gz"
else
log_error "镜像导出失败"
exit 1
fi
}
# 同步代码到服务器
sync_code() {
log_info "同步代码到服务器..."
# 创建临时目录用于同步
TEMP_DIR=$(mktemp -d)
# 复制需要的文件
cp -r . "$TEMP_DIR/"
# 删除不需要的文件
cd "$TEMP_DIR"
rm -rf node_modules
# 保留vendor目录因为服务器上缺少Octane包
rm -rf storage/logs/*.log
rm -rf storage/framework/cache/data/*
rm -rf storage/framework/sessions/*
rm -rf storage/framework/views/*
rm -rf .git
rm -rf tests
rm -rf docs
rm -rf .DS_Store
rm -rf *.tar.gz
# 同步到服务器
sshpass -p "${SERVER_PASSWORD}" rsync -avz --delete \
--exclude='storage/mysql/' \
--exclude='storage/redis/' \
--exclude='storage/meilisearch/' \
--exclude='storage/app/documents/' \
--exclude='storage/app/markdown/' \
"$TEMP_DIR/" "${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/"
# 清理临时目录
rm -rf "$TEMP_DIR"
log_info "代码同步完成"
}
# 上传Docker镜像
upload_image() {
log_info "上传Docker镜像到服务器..."
sshpass -p "${SERVER_PASSWORD}" scp ${IMAGE_NAME}-${IMAGE_TAG}.tar.gz \
${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/
log_info "镜像上传完成"
}
# 在服务器上部署
deploy_on_server() {
log_info "在服务器上执行部署..."
sshpass -p "${SERVER_PASSWORD}" ssh ${SERVER_USER}@${SERVER_HOST} << EOF
cd ${SERVER_PATH}
# 停止现有服务
echo "停止现有服务..."
docker-compose -f docker-compose-simple.yml down || true
# 删除旧镜像
echo "清理旧镜像..."
docker rmi ${IMAGE_NAME}:${IMAGE_TAG} || true
docker system prune -f
# 加载新镜像
echo "加载新镜像..."
docker load < ${IMAGE_NAME}-${IMAGE_TAG}.tar.gz
# 删除镜像文件
rm -f ${IMAGE_NAME}-${IMAGE_TAG}.tar.gz
# 复制生产环境配置
echo "设置生产环境配置..."
cp .env.production .env
# 生成新的APP_KEY如果需要
if grep -q "your-app-key-here" .env; then
echo "生成新的APP_KEY..."
APP_KEY=\$(openssl rand -base64 32)
sed -i "s|your-app-key-here-change-this-in-production|base64:\$APP_KEY|g" .env
fi
# 生成新的MEILISEARCH_KEY如果需要
if grep -q "your-master-key-change-this-in-production" .env; then
echo "生成新的MEILISEARCH_KEY..."
MEILI_KEY=\$(openssl rand -hex 32)
sed -i "s|your-master-key-change-this-in-production|\$MEILI_KEY|g" .env
fi
# 启动服务
echo "启动服务..."
docker-compose -f docker-compose-simple.yml up -d
# 等待服务启动
echo "等待服务启动..."
sleep 30
# 运行数据库迁移
echo "运行数据库迁移..."
docker-compose -f docker-compose-simple.yml exec -T app php artisan migrate --force
# 清理缓存
echo "清理应用缓存..."
docker-compose -f docker-compose-simple.yml exec -T app php artisan config:clear
docker-compose -f docker-compose-simple.yml exec -T app php artisan cache:clear
docker-compose -f docker-compose-simple.yml exec -T app php artisan route:clear
docker-compose -f docker-compose-simple.yml exec -T app php artisan view:clear
# 重新生成缓存
echo "重新生成缓存..."
docker-compose -f docker-compose-simple.yml exec -T app php artisan config:cache
docker-compose -f docker-compose-simple.yml exec -T app php artisan route:cache
docker-compose -f docker-compose-simple.yml exec -T app php artisan view:cache
# 创建搜索索引
echo "创建搜索索引..."
docker-compose -f docker-compose-simple.yml exec -T app php artisan scout:import || true
echo "部署完成!"
EOF
log_info "服务器部署完成"
}
# 验证部署
verify_deployment() {
log_info "验证部署状态..."
sshpass -p "${SERVER_PASSWORD}" ssh ${SERVER_USER}@${SERVER_HOST} << EOF
cd ${SERVER_PATH}
echo "=== 服务状态 ==="
docker-compose -f docker-compose-simple.yml ps
echo "=== 应用健康检查 ==="
curl -f http://localhost:8000/health || echo "健康检查失败"
echo "=== 队列状态 ==="
docker-compose -f docker-compose-simple.yml exec -T app php artisan queue:work --once --timeout=10 || echo "队列测试失败"
echo "=== Meilisearch状态 ==="
curl -f http://localhost:7700/health || echo "Meilisearch连接失败"
echo "=== 数据库连接 ==="
docker-compose -f docker-compose-simple.yml exec -T app php artisan tinker --execute="DB::connection()->getPdo(); echo 'Database connected successfully';" || echo "数据库连接失败"
EOF
log_info "部署验证完成"
}
# 清理本地文件
cleanup() {
log_info "清理本地文件..."
rm -f ${IMAGE_NAME}-${IMAGE_TAG}.tar.gz
log_info "清理完成"
}
# 主函数
main() {
log_info "开始部署知识库系统..."
check_requirements
setup_proxy
clean_local
build_image
export_image
sync_code
upload_image
deploy_on_server
verify_deployment
cleanup
log_info "部署流程全部完成!"
log_info "访问地址: http://${SERVER_HOST}:8000"
}
# 执行主函数
main "$@"