build-and-push.sh 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #!/usr/bin/env bash
  2. # ============================================================
  3. # build-and-push.sh — 鸣鹤 (MingHe) Docker 多架构镜像构建与推送
  4. # ============================================================
  5. #
  6. # 支持两种构建后端:
  7. # 1. Depot.dev(更快,需要 depot CLI)
  8. # 2. Docker Buildx(通用,Docker 自带)
  9. #
  10. # 用法:
  11. # ./build-and-push.sh # 构建并推送 latest
  12. # TAG=v0.1.0 ./build-and-push.sh # 构建并推送指定版本
  13. # PUSH=0 ./build-and-push.sh # 仅构建不推送
  14. # BUILDER=buildx ./build-and-push.sh # 强制使用 docker buildx
  15. # BUILDER=depot ./build-and-push.sh # 强制使用 depot
  16. # REPO=myuser TAG=v0.1.0 ./build-and-push.sh # 自定义仓库和版本
  17. #
  18. # 环境变量:
  19. # REPO — Docker Hub 用户名/组织名 (默认: facilisvelox)
  20. # TAG — 镜像标签 (默认: latest)
  21. # PUSH — 是否推送到仓库 1=推送 0=仅构建 (默认: 1)
  22. # BUILDER — 构建后端 depot|buildx|auto (默认: auto)
  23. # PLATFORM — 目标平台 (默认: linux/amd64,linux/arm64)
  24. #
  25. # ============================================================
  26. set -euo pipefail
  27. # ---- 配置 ----
  28. REPO="${REPO:-facilisvelox}"
  29. TAG="${TAG:-latest}"
  30. PUSH="${PUSH:-1}"
  31. BUILDER="${BUILDER:-auto}"
  32. PLATFORM="${PLATFORM:-linux/amd64,linux/arm64}"
  33. IMAGE="${REPO}/minghe"
  34. # ---- 颜色输出 ----
  35. RED='\033[0;31m'
  36. GREEN='\033[0;32m'
  37. YELLOW='\033[1;33m'
  38. CYAN='\033[0;36m'
  39. NC='\033[0m' # No Color
  40. log() { echo -e "${CYAN}[鸣鹤]${NC} $*"; }
  41. ok() { echo -e "${GREEN}[✓]${NC} $*"; }
  42. warn() { echo -e "${YELLOW}[!]${NC} $*"; }
  43. fail() { echo -e "${RED}[✗]${NC} $*"; exit 1; }
  44. # ---- 选择构建后端 ----
  45. select_builder() {
  46. if [[ "$BUILDER" == "depot" ]]; then
  47. if ! command -v depot &> /dev/null; then
  48. fail "'depot' 命令未找到,请安装或使用 BUILDER=buildx"
  49. fi
  50. echo "depot"
  51. elif [[ "$BUILDER" == "buildx" ]]; then
  52. if ! command -v docker &> /dev/null; then
  53. fail "'docker' 命令未找到"
  54. fi
  55. echo "buildx"
  56. else
  57. # auto: 优先 depot,回退 buildx
  58. if command -v depot &> /dev/null; then
  59. echo "depot"
  60. elif command -v docker &> /dev/null; then
  61. echo "buildx"
  62. else
  63. fail "未找到 'depot' 或 'docker' 命令,请安装其中之一"
  64. fi
  65. fi
  66. }
  67. SELECTED_BUILDER=$(select_builder)
  68. # ---- 确保 buildx builder 存在 ----
  69. setup_buildx() {
  70. if ! docker buildx inspect minghe-builder &> /dev/null 2>&1; then
  71. log "正在创建 buildx builder: minghe-builder"
  72. docker buildx create --name minghe-builder --use --driver docker-container
  73. else
  74. docker buildx use minghe-builder
  75. fi
  76. }
  77. # ---- 是否同时标记 latest ----
  78. ALSO_LATEST="no"
  79. [[ "$TAG" != "latest" ]] && ALSO_LATEST="yes"
  80. # ---- 构建函数 ----
  81. build_and_push() {
  82. local name="$1"
  83. local context="$2"
  84. local tag="$3"
  85. local also_latest="$4"
  86. # 构建 tag 参数列表
  87. local tags=("-t" "${name}:${tag}")
  88. [[ "$also_latest" == "yes" && "$tag" != "latest" ]] && tags+=("-t" "${name}:latest")
  89. local tag_display="${name}:${tag}"
  90. [[ "$also_latest" == "yes" && "$tag" != "latest" ]] && tag_display="${tag_display}, ${name}:latest"
  91. log "构建镜像: ${tag_display}"
  92. log "架构: ${PLATFORM}"
  93. log "构建后端: ${SELECTED_BUILDER}"
  94. if [[ "$SELECTED_BUILDER" == "depot" ]]; then
  95. # ---- Depot 构建 ----
  96. if [[ "$PUSH" == "1" ]]; then
  97. log "模式: 构建 + 推送 (depot)"
  98. depot build \
  99. --platform "$PLATFORM" \
  100. "${tags[@]}" \
  101. --push \
  102. "$context"
  103. else
  104. log "模式: 仅构建 (depot)"
  105. depot build \
  106. --platform "$PLATFORM" \
  107. "${tags[@]}" \
  108. --load \
  109. "$context"
  110. fi
  111. else
  112. # ---- Docker Buildx 构建 ----
  113. setup_buildx
  114. if [[ "$PUSH" == "1" ]]; then
  115. log "模式: 构建 + 推送 (buildx)"
  116. docker buildx build \
  117. --platform "$PLATFORM" \
  118. "${tags[@]}" \
  119. --push \
  120. "$context"
  121. else
  122. log "模式: 仅构建 (buildx)"
  123. # --load 不支持多平台,单平台时使用 --load,多平台时只构建不加载
  124. if [[ "$PLATFORM" == *","* ]]; then
  125. warn "多平台构建不推送时无法加载到本地 Docker,仅验证构建"
  126. docker buildx build \
  127. --platform "$PLATFORM" \
  128. "${tags[@]}" \
  129. "$context"
  130. else
  131. docker buildx build \
  132. --platform "$PLATFORM" \
  133. "${tags[@]}" \
  134. --load \
  135. "$context"
  136. fi
  137. fi
  138. fi
  139. }
  140. # ---- 主流程 ----
  141. echo ""
  142. echo " ╔═══════════════════════════════════════╗"
  143. echo " ║ 鸣鹤 MingHe — Docker 镜像构建 ║"
  144. echo " ╚═══════════════════════════════════════╝"
  145. echo ""
  146. log "仓库: ${REPO}"
  147. log "标签: ${TAG}"
  148. log "推送: $([ "$PUSH" == "1" ] && echo "是" || echo "否")"
  149. log "构建器: ${SELECTED_BUILDER}"
  150. log "目标平台: ${PLATFORM}"
  151. echo ""
  152. # 构建鸣鹤 SIP 服务器镜像
  153. build_and_push "$IMAGE" "." "$TAG" "$ALSO_LATEST"
  154. echo ""
  155. ok "构建完成!"
  156. echo ""
  157. if [[ "$PUSH" == "1" ]]; then
  158. ok "镜像已推送:"
  159. echo " docker pull ${IMAGE}:${TAG}"
  160. [[ "$ALSO_LATEST" == "yes" ]] && echo " docker pull ${IMAGE}:latest"
  161. else
  162. ok "镜像已构建(本地):"
  163. echo " docker images ${IMAGE}"
  164. fi
  165. echo ""
  166. echo " 运行方式:"
  167. echo " docker compose up -d"
  168. echo " 或:"
  169. echo " docker run -d \\"
  170. echo " -p 5061:5061/tcp \\"
  171. echo " -p 20000-20020:20000-20020/udp \\"
  172. echo " -v \$(pwd)/config:/app/config:ro \\"
  173. echo " -v minghe-certs:/app/certs \\"
  174. echo " ${IMAGE}:${TAG}"
  175. echo ""