unis_manager/deploy.sh

119 lines
4.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env bash
# 部门关键任务追踪看板 · Docker 部署脚本
# 用法: ./deploy.sh up 构建镜像并后台启动(默认命令)
# ./deploy.sh update 改完代码后重建镜像并替换容器
# ./deploy.sh restart 重启容器(不换镜像)
# ./deploy.sh down 停止并删除容器,数据留在 ./data
# ./deploy.sh logs 跟踪日志(Ctrl+C 退出)
# ./deploy.sh backup 导出数据库快照(部署到新机器时带走数据)
# ./deploy.sh status 容器状态 + 健康检查 + 访问地址
set -euo pipefail
cd "$(dirname "$0")"
CONTAINER=unis-board
# ---------- 0. 前置检查 ----------
command -v docker >/dev/null 2>&1 || { echo "!! 没有 docker 命令,请先安装 Docker / Docker Desktop" >&2; exit 1; }
docker info >/dev/null 2>&1 || { echo "!! docker 守护进程没起来(Docker Desktop 是否没运行?)" >&2; exit 1; }
if docker compose version >/dev/null 2>&1; then
COMPOSE=(docker compose)
elif command -v docker-compose >/dev/null 2>&1; then
COMPOSE=(docker-compose)
else
echo "!! 没找到 docker compose,也没找到 docker-compose" >&2
exit 1
fi
# 对外端口:命令行环境变量 > .env 里的 HOST_PORT > 8770
if [ -z "${HOST_PORT:-}" ] && [ -f .env ]; then
HOST_PORT="$(sed -n 's/^HOST_PORT=//p' .env | tail -1)"
fi
HOST_PORT="${HOST_PORT:-8770}"
URL="http://127.0.0.1:${HOST_PORT}"
# ---------- 1. 准备 .env 与 data 目录 ----------
prepare() {
if [ ! -f .env ]; then
cp .env.example .env
echo "==> 已从 .env.example 生成 .env(AI Key、管理员账号密码请按需修改,改完 restart 生效)"
fi
# 先建好目录,免得 Docker 用 root 建出来盖掉宿主机权限
mkdir -p data/uploads data/exports
}
# ---------- 2. 等服务就绪 ----------
wait_ready() {
echo -n "==> 等待服务就绪 "
for _ in $(seq 1 30); do
state="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$CONTAINER" 2>/dev/null || echo missing)"
case "$state" in
healthy) echo; echo "==> 已就绪:$URL"; return 0 ;;
unhealthy) echo; echo "!! 容器不健康,执行 ./deploy.sh logs 看原因" >&2; return 1 ;;
esac
echo -n "."
sleep 2
done
echo; echo "!! 等待超时(当前状态:$state),执行 ./deploy.sh logs 看原因" >&2
return 1
}
# ---------- 3. 分发命令 ----------
case "${1:-up}" in
up|start)
first_run=0
[ -f data/board.db ] || first_run=1
prepare
"${COMPOSE[@]}" up -d --build
wait_ready
echo " API 文档:$URL/api/docs"
if [ "$first_run" = "1" ]; then
echo " 首次启动:管理员账号取自 .env 的 ADMIN_USERNAME/ADMIN_PASSWORD(默认 admin / admin123,请登录后立刻改密码)"
fi
;;
update)
prepare
"${COMPOSE[@]}" up -d --build --force-recreate
wait_ready
;;
restart)
"${COMPOSE[@]}" restart
wait_ready
;;
down|stop)
"${COMPOSE[@]}" down
echo "==> 已停止(数据仍在 ./data,要备份请复制 data/board.db)"
;;
logs)
exec "${COMPOSE[@]}" logs -f --tail=100
;;
backup)
# 用 SQLite 备份 API 取一致性快照:服务正在写也不会拷到半截页
[ -f data/board.db ] || { echo "!! 没找到 data/board.db(若已换 MySQL,请改用 mysqldump)" >&2; exit 1; }
PYBIN="$(command -v python3 || command -v python || true)"
[ -n "$PYBIN" ] || { echo "!! 备份需要 python3(只拷库,不用装项目依赖)" >&2; exit 1; }
mkdir -p data/backups
OUT="data/backups/board-$(date +%Y%m%d_%H%M%S).db"
"$PYBIN" - "$OUT" <<'PYEOF'
import os, sqlite3, sys
src = sqlite3.connect("data/board.db")
dst = sqlite3.connect(sys.argv[1])
with dst:
src.backup(dst)
print(f"[ok] 已导出 {sys.argv[1]}({os.path.getsize(sys.argv[1]) // 1024} KB)")
PYEOF
echo "==> 部署到新机器:把这个文件放到目标机的 data/board.db,再执行 ./deploy.sh up"
;;
status)
"${COMPOSE[@]}" ps
echo -n "==> /health:"
curl -s --max-time 3 "$URL/health" 2>/dev/null || echo " 无响应(容器未启动?./deploy.sh up)"
echo
echo "==> 访问地址:$URL"
;;
*)
sed -n '3,9p' "$0"
exit 1
;;
esac