| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- #!/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
- # 函数:打印颜色信息
- 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
- 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 ""
- 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 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 ""
- 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 "════════════════════════════════════════════════════════════"
- 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 ""
|