Files
FastapiAdmin/deploy.sh
T
zhangtao a8d29d4ab4 fix: 修复多项后端缺陷并加固安全与限流
- 修正 AI 会话表初始化及异步数据库 URI 处理
- 新增全局 API 与 WS 聊天限流,健康检查豁免
- 修复忘记密码接口防用户枚举与参数校验
- 修复 SSE 推送数据重复编码问题
- 修复 Cron 表达式 Quartz 问号兼容
- 修复存储模块权限标识前缀
- 新增过期日志清理与任务错误中文提示
2026-09-07 00:08:00 +08:00

162 lines
5.4 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# ==================== 配置 ====================
# 部署方式:本地开发完成后将项目目录上传至服务器(scp/FTP/面板均可),
# 再在服务器上执行本脚本完成构建与启动——脚本不再从 git 拉取代码。
PROJECT_NAME="FastapiAdmin"
WORK_DIR="$(cd "$(dirname "$0")" && pwd)"
DOCKER_DIR="${WORK_DIR}/docker"
ENV_FILE="${DOCKER_DIR}/.env"
COLOR_GREEN='\033[0;32m'; COLOR_BLUE='\033[0;34m'; COLOR_YELLOW='\033[0;33m'; COLOR_RED='\033[0;31m'; COLOR_RESET='\033[0m'
log() {
local color; local level=${2:-INFO}
case $level in
INFO) color="${COLOR_BLUE}" ;; WARN) color="${COLOR_YELLOW}" ;;
ERROR) color="${COLOR_RED}" ;; SUCCESS) color="${COLOR_GREEN}" ;;
*) color="${COLOR_RESET}" ;;
esac
echo -e "${color}[$(date '+%Y-%m-%d %H:%M:%S')] [${level}] ${1}${COLOR_RESET}"
}
# ==================== 核心函数 ====================
load_env() {
if [ -f "${ENV_FILE}" ]; then
set -a; source "${ENV_FILE}"; set +a
elif [ -f "${DOCKER_DIR}/.env.example" ]; then
cp "${DOCKER_DIR}/.env.example" "${ENV_FILE}"
set -a; source "${ENV_FILE}"; set +a
log "已从 .env.example 生成 ${ENV_FILE},请先填写密码等配置后重新执行" "WARN"
exit 1
else
log ".env 文件不存在" "ERROR"; exit 1
fi
log "✅ 环境变量已加载" "SUCCESS"
}
check_deps() {
for dir in "${DOCKER_DIR}/mysql/data" "${DOCKER_DIR}/redis/data" "${DOCKER_DIR}/mysql/init" "${DOCKER_DIR}/redis/conf" "${WORK_DIR}/backend/static/upload"; do
[ -d "$dir" ] || mkdir -p "$dir"
done
local missing=()
for cmd in docker; do
command -v $cmd &>/dev/null || missing+=($cmd)
done
if ! docker compose version &>/dev/null && ! docker-compose --version &>/dev/null; then
missing+=("docker compose")
fi
if [ ${#missing[@]} -gt 0 ]; then
log "缺少依赖: ${missing[*]}" "ERROR"; exit 1
fi
log "✅ 依赖检查通过" "SUCCESS"
}
check_code() {
# 代码由用户上传,这里仅校验关键文件齐全
local missing=()
[ -f "${WORK_DIR}/backend/main.py" ] || missing+=("backend/main.py")
[ -f "${DOCKER_DIR}/backend/Dockerfile" ] || missing+=("docker/backend/Dockerfile")
[ -f "${DOCKER_DIR}/redis/conf/redis.conf" ] || missing+=("docker/redis/conf/redis.conf")
if [ ${#missing[@]} -gt 0 ]; then
log "代码不完整,缺少: ${missing[*]}(请重新上传后重试)" "ERROR"; exit 1
fi
log "✅ 代码完整性检查通过" "SUCCESS"
}
build_image() {
cd "${DOCKER_DIR}"
export DOCKER_BUILDKIT=1
docker compose build || { log "镜像构建失败" "ERROR"; exit 1; }
log "✅ 镜像构建完成" "SUCCESS"
}
start_service() {
cd "${DOCKER_DIR}"
docker compose up -d --force-recreate || { log "容器启动失败" "ERROR"; exit 1; }
log "⏳ 等待服务就绪..."
for i in $(seq 1 30); do
if docker compose ps mysql --format '{{.Status}}' 2>/dev/null | grep -q "healthy"; then
log "✅ MySQL 已就绪" "SUCCESS"; break
fi
sleep 2
done
docker compose ps
log "✅ 服务启动完成" "SUCCESS"
}
stop_service() {
cd "${DOCKER_DIR}" 2>/dev/null || true
docker compose down 2>/dev/null || true
log "✅ 服务已停止" "SUCCESS"
}
show_logs() {
cd "${DOCKER_DIR}"
docker compose ps --format "table {{.Service}}\t{{.Name}}\t{{.Status}}\t{{.Ports}}"
echo "--- 最近 50 行日志 ---"
docker compose logs --tail=50 2>/dev/null
}
verify() {
local ok=true
for svc in mysql redis backend nginx; do
local st=$(docker compose ps "$svc" --format '{{.Status}}' 2>/dev/null || echo "not found")
if echo "$st" | grep -qE "Up|healthy"; then
log "✅ $svc: $st" "SUCCESS"
else
log "❌ $svc: $st" "ERROR"; ok=false
fi
done
$ok && log "✅ 所有服务正常" "SUCCESS" || log "⚠️ 部分服务异常" "WARN"
}
cleanup() {
# 仅清理悬空镜像/网络/构建缓存;-a 会删掉服务器上其他项目的未使用镜像,慎用
docker image prune -f >/dev/null 2>&1 || true
docker builder prune -f >/dev/null 2>&1 || true
log "✅ 构建缓存已清理" "SUCCESS"
}
# ==================== 主流程 ====================
full_deploy() {
log "========== 🚀 开始完整部署 ==========" "INFO"
log "时间: $(date '+%Y-%m-%d %H:%M:%S')"
load_env
check_deps
check_code
build_image
start_service
verify
show_logs
cleanup
log "========== 🎉 部署完成 ==========" "SUCCESS"
}
# ==================== 入口 ====================
trap 'stop_service; exit 130' INT TERM
case ${1:-} in
start) load_env; start_service ;;
stop) load_env; stop_service ;;
restart) load_env; cd "${DOCKER_DIR}"; docker compose restart; docker compose ps ;;
logs) load_env; show_logs ;;
verify) load_env; verify ;;
clean) cleanup ;;
help|-h|--help)
echo "用法: $0 [命令]"
echo " 无参数 完整部署(校验代码→构建→启动→清理;代码需先上传至服务器)"
echo " start 启动服务"
echo " stop 停止服务"
echo " restart 重启服务"
echo " logs 查看日志"
echo " verify 验证服务"
echo " clean 清理构建缓存"
;;
*) full_deploy "$@" ;;
esac