#!/bin/bash # 目前采用github action自动版本构建,用 # git tag v1.0.9 # git push origin v1.0.9 # ============================================ # Docker Hub 镜像推送脚本 # 用途:构建并推送所有服务镜像到 Docker Hub # 多架构构建:./docker-push.sh -p linux/amd64,linux/arm64 worker # ============================================ set -e # 启用 BuildKit(支持高级缓存功能) export DOCKER_BUILDKIT=1 # ==================== 配置 ==================== # 切换到脚本所在目录(项目根目录) SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" # 从 Git Tag 获取版本号(必须有 tag 才能构建) get_version() { local tag tag=$(git describe --tags --exact-match 2>/dev/null) if [ -n "$tag" ]; then echo "$tag" else echo -e "\033[0;31m[ERROR]\033[0m 当前 commit 没有 Git Tag,无法构建" echo " 请先打 tag: git tag v1.x.x && git push --tags" exit 1 fi } GIT_VERSION=$(get_version) # Docker Hub 用户名(修改为你的用户名) DOCKER_USER="${DOCKER_USER:-yyhuni}" # 镜像版本标签(从 Git Tag 获取) VERSION="$GIT_VERSION" # 是否推送(默认 yes,设为 no 则只构建不推送) PUSH="${PUSH:-yes}" # 构建平台(默认当前架构,可设为 linux/amd64,linux/arm64 进行多架构构建) PLATFORM="${PLATFORM:-}" # 镜像列表 IMAGES=( "xingrin-server:docker/server/Dockerfile" "xingrin-frontend:docker/frontend/Dockerfile" "xingrin-nginx:docker/nginx/Dockerfile" "xingrin-worker:docker/worker/Dockerfile" "xingrin-agent:docker/agent/Dockerfile" ) # 颜色 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } # ==================== 帮助信息 ==================== show_help() { cat << EOF 用法: $0 [选项] [镜像名...] 版本号从 Git Tag 自动获取,无 tag 时使用 dev-。 选项: -u, --user USER Docker Hub 用户名 (默认: $DOCKER_USER) -p, --platform PLAT 构建平台 (如: linux/amd64,linux/arm64) --no-push 只构建不推送 -h, --help 显示帮助 镜像名 (可选,不指定则构建全部): server 后端服务 frontend 前端服务 nginx Nginx 反向代理 worker 扫描 Worker agent 心跳上报 Agent(轻量) 示例: $0 # 构建并推送所有镜像 $0 server frontend # 只构建 server 和 frontend $0 --no-push # 只构建不推送 $0 -p linux/amd64,linux/arm64 # 多架构构建 环境变量: DOCKER_USER Docker Hub 用户名 PUSH 是否推送 (yes/no) PLATFORM 构建平台 EOF exit 0 } # ==================== 解析参数 ==================== SELECTED_IMAGES=() while [[ $# -gt 0 ]]; do case $1 in -u|--user) DOCKER_USER="$2" shift 2 ;; -p|--platform) PLATFORM="$2" shift 2 ;; --no-push) PUSH="no" shift ;; -h|--help) show_help ;; server|frontend|nginx|worker|agent) SELECTED_IMAGES+=("$1") shift ;; *) log_error "未知参数: $1" show_help ;; esac done # ==================== 检查 Docker 登录 ==================== check_docker_login() { if [ "$PUSH" = "yes" ]; then log_info "检查 Docker Hub 登录状态..." if ! docker info 2>/dev/null | grep -q "Username"; then log_warn "未登录 Docker Hub,请先执行: docker login" read -p "是否现在登录?(y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then docker login else log_error "需要登录才能推送镜像" exit 1 fi fi log_success "Docker Hub 已登录" fi } # ==================== 构建镜像 ==================== build_image() { local name=$1 local dockerfile=$2 local full_name="${DOCKER_USER}/${name}:${VERSION}" log_info "构建镜像: $full_name" log_info " Dockerfile: $dockerfile" # 构建命令 local build_cmd="docker build" # 多架构构建使用 buildx if [ -n "$PLATFORM" ]; then build_cmd="docker buildx build --platform $PLATFORM" if [ "$PUSH" = "yes" ]; then build_cmd="$build_cmd --push" fi fi # 执行构建(只打版本标签,不打 latest) $build_cmd \ -t "$full_name" \ -f "$dockerfile" \ . if [ $? -eq 0 ]; then log_success "构建成功: $full_name" else log_error "构建失败: $full_name" exit 1 fi # 推送(非 buildx 模式) if [ "$PUSH" = "yes" ] && [ -z "$PLATFORM" ]; then log_info "推送镜像: $full_name" docker push "$full_name" log_success "推送成功: $full_name" fi } # ==================== 主流程 ==================== main() { echo "" echo "==========================================" echo " Docker Hub 镜像构建与推送" echo "==========================================" echo "" log_info "用户: $DOCKER_USER" log_warn "版本: ${VERSION}" log_info "推送: $PUSH" [ -n "$PLATFORM" ] && log_info "平台: $PLATFORM" echo "" # 确认版本号,防止误覆盖 if [ "$PUSH" = "yes" ]; then echo -e "${YELLOW}[!] 请确认版本号 ${VERSION} 是否正确${NC}" echo -e "${YELLOW} 如需修改,请打新的 Git Tag: git tag v1.x.x${NC}" echo -e "${RED} 覆盖版本号会导致所有用户的旧版本拉取出现问题!!!${NC}" read -p "确认推送?(y/N) " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then log_info "已取消" exit 0 fi fi check_docker_login # 切换到项目根目录 cd "$(dirname "$0")" # 如果指定了特定镜像,只构建那些 if [ ${#SELECTED_IMAGES[@]} -gt 0 ]; then for sel in "${SELECTED_IMAGES[@]}"; do for item in "${IMAGES[@]}"; do name="${item%%:*}" dockerfile="${item##*:}" if [[ "$name" == "xingrin-$sel" ]]; then build_image "$name" "$dockerfile" fi done done else # 构建所有镜像 for item in "${IMAGES[@]}"; do name="${item%%:*}" dockerfile="${item##*:}" build_image "$name" "$dockerfile" done fi echo "" echo "==========================================" log_success " 完成!" echo "==========================================" echo "" if [ "$PUSH" = "yes" ]; then log_info "镜像已推送到 Docker Hub:" for item in "${IMAGES[@]}"; do name="${item%%:*}" echo " - docker pull ${DOCKER_USER}/${name}:${VERSION}" done fi } main