選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

181 行
4.4 KiB

  1. #!/bin/bash
  2. # scripts/deploy.sh - 构建镜像并部署到国内/国外服务器
  3. #
  4. # 用法 (在 Windows 中通过 WSL 调用):
  5. # wsl -- bash -c "bash /mnt/d/code/new-api/scripts/deploy.sh [选项]"
  6. #
  7. # 选项:
  8. # (无参数) 构建镜像 + 推送 + 部署到两台服务器
  9. # cn 只部署到国内服务器
  10. # ov 只部署到国外服务器
  11. # --no-build 跳过构建推送,使用本地最新镜像部署
  12. # --no-build cn 可组合
  13. #
  14. # 前提: WSL 中已配置 SSH 免密登录到两台服务器
  15. set -euo pipefail
  16. # ==================== 配置 ====================
  17. DOCKER_REGISTRY="registry.cn-hangzhou.aliyuncs.com/fengsilin/new-api"
  18. PROJECT_DIR="/mnt/d/code/new-api"
  19. # 服务器: SSH_HOST COMPOSE_DIR
  20. CN_HOST="root@123.57.74.135"
  21. CN_DIR="/root/new-api"
  22. OV_HOST="root@139.180.189.205"
  23. OV_DIR="/root/new-api/new-api"
  24. # ==================== 颜色 ====================
  25. RED='\033[0;31m'
  26. GREEN='\033[0;32m'
  27. YELLOW='\033[1;33m'
  28. CYAN='\033[0;36m'
  29. BOLD='\033[1m'
  30. NC='\033[0m'
  31. info() { echo -e " ${CYAN}[INFO]${NC} $*"; }
  32. ok() { echo -e " ${GREEN}[OK]${NC} $*"; }
  33. warn() { echo -e " ${YELLOW}[WARN]${NC} $*"; }
  34. error() { echo -e " ${RED}[ERROR]${NC} $*"; }
  35. section() {
  36. echo ""
  37. echo -e " ${BOLD}=========================================${NC}"
  38. echo -e " ${BOLD} $*${NC}"
  39. echo -e " ${BOLD}=========================================${NC}"
  40. }
  41. # ==================== 参数解析 ====================
  42. TARGET="all"
  43. NO_BUILD=false
  44. for arg in "$@"; do
  45. case "$arg" in
  46. cn) TARGET="cn" ;;
  47. ov) TARGET="ov" ;;
  48. --no-build) NO_BUILD=true ;;
  49. -h|--help)
  50. echo "用法: $0 [cn|ov] [--no-build]"
  51. exit 0
  52. ;;
  53. *)
  54. error "未知参数: $arg"
  55. exit 1
  56. ;;
  57. esac
  58. done
  59. # ==================== Step 1: 构建并推送 ====================
  60. if [ "$NO_BUILD" = false ]; then
  61. section "Step 1/2: 构建并推送镜像"
  62. cd "$PROJECT_DIR"
  63. BRANCH=$(git rev-parse --abbrev-ref HEAD | sed 's/\//-/g')
  64. COMMIT_SHORT=$(git rev-parse --short HEAD)
  65. GIT_DIRTY=""
  66. git diff --quiet && git diff --cached --quiet 2>/dev/null || GIT_DIRTY="-dirty"
  67. TAG="$(date +%Y%m%d%H%M)-${BRANCH}-${COMMIT_SHORT}${GIT_DIRTY}"
  68. IMAGE="${DOCKER_REGISTRY}:${TAG}"
  69. info "分支: ${BRANCH}"
  70. info "Tag: ${TAG}"
  71. info "镜像: ${IMAGE}"
  72. echo ""
  73. docker build -t "${IMAGE}" .
  74. echo ""
  75. info "推送镜像..."
  76. docker push "${IMAGE}"
  77. ok "构建并推送完成: ${TAG}"
  78. else
  79. section "跳过构建,查找本地最新镜像..."
  80. IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" "${DOCKER_REGISTRY}" | head -1)
  81. if [ -z "$IMAGE" ]; then
  82. error "本地未找到 ${DOCKER_REGISTRY} 的镜像"
  83. error "请先不带 --no-build 运行一次"
  84. exit 1
  85. fi
  86. TAG="${IMAGE##*:}"
  87. ok "使用镜像: ${IMAGE}"
  88. fi
  89. # ==================== Step 2: 部署 ====================
  90. section "Step 2/2: 部署到服务器"
  91. FAILED=()
  92. deploy_server() {
  93. local NAME="$1"
  94. local HOST="$2"
  95. local DIR="$3"
  96. echo ""
  97. info "部署到 ${NAME} (${HOST})..."
  98. info " 目录: ${DIR} Tag: ${TAG}"
  99. echo ""
  100. if ssh -o ConnectTimeout=15 "$HOST" bash -s "$DIR" "$DOCKER_REGISTRY" "$TAG" <<'REMOTE'; then
  101. set -e
  102. DIR="$1"
  103. REGISTRY="$2"
  104. TAG="$3"
  105. cd "$DIR"
  106. echo " [1/4] 更新 image tag..."
  107. sed -i "s|${REGISTRY}:.*|${REGISTRY}:${TAG}|" docker-compose.yml
  108. echo " [2/4] 拉取新镜像..."
  109. PULL_TIMEOUT=120
  110. for i in 1 2 3; do
  111. if timeout "${PULL_TIMEOUT}" docker compose pull --quiet new-api; then
  112. break
  113. fi
  114. if [ "$i" -eq 3 ]; then
  115. echo " [2/4] 拉取失败,已重试 3 次(每次 ${PULL_TIMEOUT}s 超时)"
  116. exit 1
  117. fi
  118. echo " [2/4] 拉取超时或失败(${PULL_TIMEOUT}s),第 $((i+1)) 次重试..."
  119. sleep 5
  120. done
  121. echo " [3/4] 重启服务..."
  122. docker compose up -d new-api
  123. echo " [4/4] 等待启动..."
  124. sleep 8
  125. docker compose ps new-api
  126. docker image prune -f >/dev/null 2>&1
  127. REMOTE
  128. ok "${NAME} 部署成功"
  129. else
  130. error "${NAME} 部署失败"
  131. FAILED+=("$NAME")
  132. fi
  133. }
  134. case "$TARGET" in
  135. cn) deploy_server "国内(CN)" "$CN_HOST" "$CN_DIR" ;;
  136. ov) deploy_server "国外(OV)" "$OV_HOST" "$OV_DIR" ;;
  137. all)
  138. deploy_server "国内(CN)" "$CN_HOST" "$CN_DIR"
  139. deploy_server "国外(OV)" "$OV_HOST" "$OV_DIR"
  140. ;;
  141. esac
  142. # ==================== 总结 ====================
  143. echo ""
  144. section "部署总结"
  145. echo -e " 镜像: ${GREEN}${IMAGE}${NC}"
  146. if [ ${#FAILED[@]} -gt 0 ]; then
  147. error "失败节点: ${FAILED[*]}"
  148. exit 1
  149. else
  150. ok "全部节点部署成功"
  151. fi