|
|
@@ -2,72 +2,357 @@
|
|
|
|
|
|
# ============================================
|
|
|
# 快速 Docker 构建脚本 - 使用优化版 Dockerfile
|
|
|
-# 构建前请先执行:bash init-dependencies.sh
|
|
|
+# 使用文档:
|
|
|
+# 首次使用: 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 -e
|
|
|
-
|
|
|
-SERVICE=${1:-gateway}
|
|
|
-TAG=${2:-latest}
|
|
|
-REGISTRY=${3:-localhost:5000}
|
|
|
-
|
|
|
-BUILD_NUMBER=$(date +%Y%m%d%H%M%S)
|
|
|
-GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
|
|
-
|
|
|
-case $SERVICE in
|
|
|
- gateway)
|
|
|
- DOCKERFILE="shop-recycle-gateway/Dockerfile.optimized"
|
|
|
- IMAGE_NAME="$REGISTRY/shop-recycle-gateway:$TAG"
|
|
|
- ;;
|
|
|
- order)
|
|
|
- DOCKERFILE="shop-recycle-order-service/Dockerfile.optimized"
|
|
|
- IMAGE_NAME="$REGISTRY/shop-recycle-order-service:$TAG"
|
|
|
- ;;
|
|
|
- payment)
|
|
|
- DOCKERFILE="shop-recycle-payment-service/Dockerfile.optimized"
|
|
|
- IMAGE_NAME="$REGISTRY/shop-recycle-payment-service:$TAG"
|
|
|
- ;;
|
|
|
- *)
|
|
|
- echo "未知服务: $SERVICE"
|
|
|
- echo "用法: $0 [gateway|order|payment] [tag] [registry]"
|
|
|
- exit 1
|
|
|
- ;;
|
|
|
-esac
|
|
|
-
|
|
|
-echo "════════════════════════════════════════════════════════════"
|
|
|
-echo "快速构建 - 使用优化版 Dockerfile"
|
|
|
-echo "════════════════════════════════════════════════════════════"
|
|
|
-echo "服务: $SERVICE"
|
|
|
-echo "TAG: $TAG"
|
|
|
-echo "镜像: $IMAGE_NAME"
|
|
|
-echo "Commit: $GIT_COMMIT"
|
|
|
-echo ""
|
|
|
+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
|
|
|
+
|
|
|
+# 函数:打印颜色信息
|
|
|
+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)
|
|
|
+ --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
|
|
|
|
|
|
-# 检查 Dockerfile 是否存在
|
|
|
-if [ ! -f "$DOCKERFILE" ]; then
|
|
|
- echo "❌ 错误: $DOCKERFILE 不存在"
|
|
|
+EOF
|
|
|
+}
|
|
|
+
|
|
|
+# 参数处理
|
|
|
+REGISTRY="harbor.stardance"
|
|
|
+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 ""
|
|
|
- echo "首次使用时,请先执行初始化脚本:"
|
|
|
- echo " bash init-dependencies.sh"
|
|
|
- echo " bash build-docker-optimized.sh $SERVICE $TAG"
|
|
|
+ show_help
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
-echo ">>> 开始构建..."
|
|
|
-docker build \
|
|
|
- --build-arg BUILD_NUMBER="$BUILD_NUMBER" \
|
|
|
- --build-arg GIT_COMMIT="$GIT_COMMIT" \
|
|
|
- -t "$IMAGE_NAME" \
|
|
|
- -f "$DOCKERFILE" \
|
|
|
- .
|
|
|
+# 函数:解析 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 build_number=$(date +%Y%m%d%H%M%S)
|
|
|
+ local git_commit=$(git rev-parse --short HEAD 2>/dev/null ; echo "unknown")
|
|
|
+ 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\" -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[@]} 个镜像"
|
|
|
+
|
|
|
+# 检查 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 "════════════════════════════════════════════════════════════"
|
|
|
-echo "✅ 构建完成!"
|
|
|
-echo "════════════════════════════════════════════════════════════"
|
|
|
echo ""
|
|
|
-echo "镜像详细信息:"
|
|
|
-docker images | grep "$REGISTRY" | head -3
|
|
|
+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 ""
|
|
|
-echo "运行容器: docker run -d -p 8080:8080 $IMAGE_NAME"
|
|
|
+log_info "════════════════════════════════════════════════════════════"
|
|
|
+log_info "下一步操作:"
|
|
|
+log_info "════════════════════════════════════════════════════════════"
|
|
|
+echo " # 查看镜像列表"
|
|
|
+echo " docker images | grep harbor.stardance"
|
|
|
+echo ""
|
|
|
+echo " # 运行容器"
|
|
|
+echo " docker run -d -p 8080:8080 --name gateway-container \\"
|
|
|
+echo " harbor.stardance/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 ""
|
|
|
+
|