#!/bin/bash # ============================================ # 快速 Docker 构建脚本 - 使用优化版 Dockerfile # 使用文档: # 首次使用: bash init-dependencies.sh # 构建单个: bash build-docker-optimized.sh gateway:1.0.0 # 构建多个: bash build-docker-optimized.sh gateway:3.0.2 order-service:3.0.5 payment-service:3.0.5 # 自定义仓库: bash build-docker-optimized.sh gateway:1.0.0 -r myregistry.com # ============================================ set -o pipefail # 管道中任何命令失败都会导致脚本退出 # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color # 全局构建参数(同一次构建中所有镜像共享) BUILD_NUMBER=$(date +%Y%m%d%H%M%S) GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null ; echo "unknown") # 函数:打印颜色信息 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[✓]${NC} $1" } log_error() { echo -e "${RED}[✗]${NC} $1" >&2 } log_warn() { echo -e "${YELLOW}[!]${NC} $1" } log_title() { echo -e "${CYAN}$1${NC}" } # 函数:显示使用帮助 show_help() { cat << EOF 用法: $0 [OPTIONS] SERVICE:TAG [SERVICE:TAG] ... 服务简称: gateway - shop-recycle-gateway 网关服务 order - shop-recycle-order-service 订单服务 order-service - shop-recycle-order-service (别名) payment - shop-recycle-payment-service 支付服务 payment-service - shop-recycle-payment-service (别名) 全局选项: -h, --help 显示此帮助信息 -r, --registry ADDR 镜像仓库地址 (默认: harbor.stardance/shoprecycle) --no-cache 构建时不使用缓存 --push 构建完成后自动推送到镜像仓库 示例: # 构建单个服务 bash $0 gateway:1.0.0 # 构建多个服务(依次进行) bash $0 gateway:3.0.2 order-service:3.0.5 payment-service:3.0.5 # 自定义镜像仓库 bash $0 gateway:1.0.0 -r myregistry.com # 禁用缓存并推送 bash $0 gateway:1.0.0 --no-cache --push EOF } # 参数处理 REGISTRY="harbor.stardance/shoprecycle" NO_CACHE="" PUSH_IMAGE=false BUILD_TARGETS=() # 解析参数 while [[ $# -gt 0 ]]; do case $1 in -h|--help) show_help exit 0 ;; -r|--registry) REGISTRY="$2" shift 2 ;; --no-cache) NO_CACHE="--no-cache" shift ;; --push) PUSH_IMAGE=true shift ;; *) # 服务:标签 格式的参数 BUILD_TARGETS+=("$1") shift ;; esac done # 验证必要参数 if [ ${#BUILD_TARGETS[@]} -eq 0 ]; then log_error "缺少构建目标" echo "" show_help exit 1 fi # 函数:解析 service:tag 格式 parse_service_tag() { local input="$1" if [[ ! "$input" =~ : ]]; then log_error "格式错误: $input (应为 service:tag 格式)" return 1 fi local service="${input%%:*}" local tag="${input##*:}" # 映射服务名称 local dockerfile="" local image_name="" case "$service" in gateway) dockerfile="shop-recycle-gateway/Dockerfile.optimized" image_name="$REGISTRY/shop-recycle-gateway:$tag" ;; order|order-service) dockerfile="shop-recycle-order-service/Dockerfile.optimized" image_name="$REGISTRY/shop-recycle-order-service:$tag" ;; payment|payment-service) dockerfile="shop-recycle-payment-service/Dockerfile.optimized" image_name="$REGISTRY/shop-recycle-payment-service:$tag" ;; *) log_error "未知服务: $service" return 1 ;; esac # 输出为 json 格式便于后续处理 echo "{\"service\":\"$service\",\"tag\":\"$tag\",\"dockerfile\":\"$dockerfile\",\"image\":\"$image_name\"}" } # 函数:构建单个镜像 build_image() { local service="$1" local tag="$2" local dockerfile="$3" local image_name="$4" # 检查 Dockerfile 是否存在 if [ ! -f "$dockerfile" ]; then log_error "Dockerfile 不存在: $dockerfile" return 1 fi local start_time=$(date +%s) # 打印构建信息 echo "" log_title "════════════════════════════════════════════════════════════" log_title "Docker 镜像构建" log_title "════════════════════════════════════════════════════════════" log_info "服务: $service" log_info "镜像标签: $tag" log_info "仓库地址: $REGISTRY" log_info "镜像名称: $image_name" log_info "Git 提交: $GIT_COMMIT" log_info "构建号: $BUILD_NUMBER" [ -n "$NO_CACHE" ] && log_warn "禁用构建缓存" echo "" log_info "开始构建镜像..." echo "" # 执行 Docker 构建(传递全局构建参数) if docker build $NO_CACHE \ --build-arg BUILD_NUMBER="$BUILD_NUMBER" \ --build-arg GIT_COMMIT="$GIT_COMMIT" \ -t "$image_name" \ -f "$dockerfile" \ .; then local end_time=$(date +%s) local duration=$((end_time - start_time)) local minutes=$((duration / 60)) local seconds=$((duration % 60)) echo "" log_success "════════════════════════════════════════════════════════════" log_success "构建完成!" log_success "════════════════════════════════════════════════════════════" log_success "用时: ${minutes}分${seconds}秒" echo "" # 显示镜像信息 log_info "镜像详细信息:" docker images "$image_name" --no-trunc echo "" # 获取镜像大小 local image_size=$(docker images --format "{{.Size}}" "$image_name") log_info "镜像大小: $image_size" # 推送镜像 if [ "$PUSH_IMAGE" = true ]; then echo "" log_info "准备推送镜像到仓库: $REGISTRY" if docker push "$image_name"; then log_success "镜像推送成功!" else log_error "镜像推送失败" return 1 fi fi return 0 else local end_time=$(date +%s) local duration=$((end_time - start_time)) local minutes=$((duration / 60)) local seconds=$((duration % 60)) echo "" log_error "════════════════════════════════════════════════════════════" log_error "构建失败!用时: ${minutes}分${seconds}秒" log_error "════════════════════════════════════════════════════════════" echo "" log_error "调试建议:" echo " # 查看 Docker 构建日志(详细信息)" echo " docker build $NO_CACHE --build-arg BUILD_NUMBER=\"$BUILD_NUMBER\" --build-arg GIT_COMMIT=\"$GIT_COMMIT\" -t \"$image_name\" -f \"$dockerfile\" . --progress=plain" echo "" return 1 fi } # 主程序流程 echo "" log_title "╔════════════════════════════════════════════════════════════╗" log_title "║ Shop Recycle Docker 批量构建工具 ║" log_title "╚════════════════════════════════════════════════════════════╝" echo "" # 解析所有构建目标 declare -a services declare -a tags declare -a dockerfiles declare -a images log_info "解析构建目标..." for target in "${BUILD_TARGETS[@]}"; do parsed=$(parse_service_tag "$target") if [ $? -ne 0 ]; then log_error "无法解析构建目标: $target" exit 1 fi # 从 json 中提取字段 service=$(echo "$parsed" | grep -o '"service":"[^"]*"' | cut -d'"' -f4) tag=$(echo "$parsed" | grep -o '"tag":"[^"]*"' | cut -d'"' -f4) dockerfile=$(echo "$parsed" | grep -o '"dockerfile":"[^"]*"' | cut -d'"' -f4) image=$(echo "$parsed" | grep -o '"image":"[^"]*"' | cut -d'"' -f4) services+=("$service") tags+=("$tag") dockerfiles+=("$dockerfile") images+=("$image") log_success "$target" done echo "" log_info "将按顺序构建 ${#BUILD_TARGETS[@]} 个镜像" log_info "全局构建号: $BUILD_NUMBER" log_info "全局 Git 提交: $GIT_COMMIT" # 检查 git 仓库状态 if [ -z "$(git status --porcelain 2>/dev/null)" ]; then log_success "Git 工作目录干净" else log_warn "Git 工作目录有未提交的更改" fi echo "" # 依次构建每个镜像 failed_builds=() successful_builds=() for i in "${!services[@]}"; do echo "" log_title "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_title "进度: $((i+1))/${#BUILD_TARGETS[@]} - ${BUILD_TARGETS[$i]}" log_title "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" if build_image "${services[$i]}" "${tags[$i]}" "${dockerfiles[$i]}" "${images[$i]}"; then successful_builds+=("${BUILD_TARGETS[$i]}") else failed_builds+=("${BUILD_TARGETS[$i]}") log_error "构建失败: ${BUILD_TARGETS[$i]}" exit 1 fi done # 汇总报告 echo "" echo "" log_title "╔════════════════════════════════════════════════════════════╗" log_title "║ 构建汇总 ║" log_title "╚════════════════════════════════════════════════════════════╝" echo "" log_success "成功构建 ${#successful_builds[@]} 个镜像:" for build in "${successful_builds[@]}"; do echo " ✓ $build" done if [ ${#failed_builds[@]} -gt 0 ]; then echo "" log_error "失败 ${#failed_builds[@]} 个:" for build in "${failed_builds[@]}"; do echo " ✗ $build" done fi echo "" log_info "════════════════════════════════════════════════════════════" log_info "构建信息:" log_info "════════════════════════════════════════════════════════════" log_info "构建号: $BUILD_NUMBER" log_info "Git 提交: $GIT_COMMIT" echo "" log_info "下一步操作:" log_info "════════════════════════════════════════════════════════════" echo " # 查看镜像列表" echo " docker images | grep harbor.stardance/shoprecycle" echo "" echo " # 运行容器" echo " docker run -d -p 8080:8080 --name gateway-container \\" echo " harbor.stardance/shoprecycle/shop-recycle-gateway:3.0.2" echo "" if [ "$PUSH_IMAGE" = false ]; then echo " # 推送所有镜像到仓库" for image in "${images[@]}"; do echo " docker push $image" done echo "" fi echo ""