#!/bin/bash # =================================================================== # TopFans Docker 一键构建脚本 # 功能:编译并打包所有后端服务为 Docker 镜像 # =================================================================== # # 使用方式: # ./build.sh # 构建所有服务(默认) # ./build.sh --no-cache # 无缓存构建 # ./build.sh gateway # 仅构建 Gateway # ./build.sh userService # 仅构建 UserService # ./build.sh prod # 使用生产配置构建 # # 示例: # ./build.sh # 构建所有服务 # ./build.sh --no-cache # 清除缓存重新构建 # ./build.sh gateway userService # 仅构建指定服务 # =================================================================== set -e # 遇到错误立即退出 # ==================== 颜色定义 ==================== # 用于终端输出彩色文字,提升可读性 RED='\033[0;31m' # 红色 - 错误信息 GREEN='\033[0;32m' # 绿色 - 成功信息 YELLOW='\033[1;33m' # 黄色 - 警告/进度信息 BLUE='\033[0;34m' # 蓝色 - 标题信息 NC='\033[0m' # 重置颜色 # ==================== 路径配置 ==================== # 获取脚本所在目录(支持从任意目录调用) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" # ==================== 构建配置 ==================== # 镜像前缀,用于标记和组织镜像(必须小写) IMAGE_PREFIX="topfans" # Dockerfile 路径 DOCKERFILE="Dockerfile.services" # 目标架构(amd64 适用于大多数服务器) TARGET_ARCH="linux/amd64" # ==================== 默认设置 ==================== # 是否使用缓存(默认使用,构建更快) NO_CACHE="" # 构建配置文件(local 或 prod) PROFILE="local" # 要构建的服务列表(留空则构建全部) SERVICES=() # ==================== 解析命令行参数 ==================== # 支持多种使用方式 # --no-cache: 清除 Docker 缓存,强制重新构建 # --profile prod: 使用生产配置 # 服务名: 仅构建指定服务(如 gateway, userService 等) while [[ $# -gt 0 ]]; do case $1 in --no-cache) # 启用无缓存构建,适用于代码更新后确保完全重新编译 NO_CACHE="--no-cache" echo -e "${YELLOW}警告: 无缓存模式,构建时间较长${NC}" shift ;; --profile) # 指定构建配置(local 或 prod) PROFILE="$2" shift 2 ;; --help|-h) # 显示帮助信息 echo "用法: $0 [选项] [服务名...]" echo "" echo "选项:" echo " --no-cache 不使用 Docker 缓存,强制重新构建" echo " --profile 使用配置文件 (local/prod),默认 local" echo " --help, -h 显示此帮助信息" echo "" echo "服务名 (可选):" echo " gateway, userService, socialService, assetService," echo " galleryService, activityService, taskService, starbookService" echo "" echo "示例:" echo " $0 # 构建所有服务" echo " $0 --no-cache # 无缓存构建所有服务" echo " $0 gateway # 仅构建 Gateway" echo " $0 --profile prod # 使用生产配置构建" exit 0 ;; *) # 未知参数,假设是服务名 # 支持的服务名映射(别名 -> 实际 target 名) case $1 in gateway) SERVICES+=("gateway") ;; user|userService) SERVICES+=("userService") ;; social|socialService) SERVICES+=("socialService") ;; asset|assetService) SERVICES+=("assetService") ;; gallery|galleryService) SERVICES+=("galleryService") ;; activity|activityService) SERVICES+=("activityService") ;; task|taskService) SERVICES+=("taskService") ;; starbook|starbookService) SERVICES+=("starbookService") ;; all) # all 关键字,构建所有服务 SERVICES=() break ;; *) echo -e "${RED}错误: 未知服务 '$1'${NC}" echo "使用 --help 查看可用服务列表" exit 1 ;; esac shift ;; esac done # ==================== 服务列表 ==================== # 所有可用服务及其配置(使用小写 target 名) ALL_SERVICES_NAME=("gateway" "userservice" "socialservice" "assetservice" "galleryservice" "activityservice" "taskservice" "starbookservice") # 确定要构建的服务 if [ ${#SERVICES[@]} -eq 0 ]; then # 未指定服务,构建全部 SERVICE_NAMES=("${ALL_SERVICES_NAME[@]}") else SERVICE_NAMES=("${SERVICES[@]}") fi # ==================== 构建函数 ==================== # 打印分隔线 print_line() { echo -e "${BLUE}========================================${NC}" } # 打印带颜色的消息 print_msg() { local color=$1 local msg=$2 echo -e "${color}${msg}${NC}" } # 构建单个服务的镜像 # 参数: service_name docker_target build_service() { local service_name=$1 local docker_target=$2 echo -e "\n${YELLOW}正在构建 ${service_name}...${NC}" # 检查 Dockerfile 是否存在 if [ ! -f "$DOCKERFILE" ]; then echo -e "${RED}错误: Dockerfile ($DOCKERFILE) 不存在${NC}" return 1 fi # 构建镜像 # 镜像命名: topfans/gateway:latest, topfans/userService:latest 等 # -f: 指定 Dockerfile # --target: 指定构建阶段(对应 Dockerfile 中的 AS xxx) # --platform: 指定目标平台 # $NO_CACHE: 是否使用缓存 docker build \ $NO_CACHE \ -f "$DOCKERFILE" \ --target "$docker_target" \ --platform "$TARGET_ARCH" \ -t "${IMAGE_PREFIX}/${service_name}:latest" \ ../ if [ $? -eq 0 ]; then print_msg "$GREEN" "✅ ${service_name} 构建成功" return 0 else print_msg "$RED" "❌ ${service_name} 构建失败" return 1 fi } # ==================== 主构建流程 ==================== main() { print_line print_msg "$BLUE" " TopFans Docker 构建脚本" print_msg "$BLUE" " 配置: ${PROFILE}" print_msg "$BLUE" " 架构: ${TARGET_ARCH}" print_line # 记录开始时间 START_TIME=$(date +%s) # 统计构建结果 SUCCESS_COUNT=0 FAIL_COUNT=0 # 构建每个服务 for service in "${SERVICE_NAMES[@]}"; do # 服务名到 target 的映射(统一使用小写 target) case $service in gateway) docker_target="gateway" ;; userservice) docker_target="userservice" ;; socialservice) docker_target="socialservice" ;; assetservice) docker_target="assetservice" ;; galleryservice) docker_target="galleryservice" ;; activityservice) docker_target="activityservice" ;; taskservice) docker_target="taskservice" ;; starbookservice) docker_target="starbookservice" ;; # 兼容旧的大写服务名 userService) docker_target="userservice" ;; socialService) docker_target="socialservice" ;; assetService) docker_target="assetservice" ;; galleryService) docker_target="galleryservice" ;; activityService) docker_target="activityservice" ;; taskService) docker_target="taskservice" ;; starbookService) docker_target="starbookservice" ;; *) docker_target="$service" ;; esac if build_service "$service" "$docker_target"; then ((SUCCESS_COUNT++)) else ((FAIL_COUNT++)) fi done # ==================== 构建结果 ==================== print_line print_msg "$BLUE" " 构建完成" # 计算耗时 END_TIME=$(date +%s) ELAPSED=$((END_TIME - START_TIME)) MINUTES=$((ELAPSED / 60)) SECONDS=$((ELAPSED % 60)) echo "" print_msg "$GREEN" "✅ 成功: ${SUCCESS_COUNT} 个服务" if [ $FAIL_COUNT -gt 0 ]; then print_msg "$RED" "❌ 失败: ${FAIL_COUNT} 个服务" fi echo -e "${YELLOW}⏱ 耗时: ${MINUTES}分${SECONDS}秒${NC}" print_line # 显示构建的镜像 echo "" print_msg "$BLUE" "构建的镜像列表:" echo "" for service in "${SERVICE_NAMES[@]}"; do # 获取镜像大小 SIZE=$(docker images "${IMAGE_PREFIX}/${service}:latest" --format "{{.Size}}" 2>/dev/null || echo "未知") echo -e " ${GREEN}${IMAGE_PREFIX}/${service}:latest${NC} (${SIZE})" done echo "" print_msg "$GREEN" "🎉 构建完成!" echo "" echo "下一步:" echo " 启动服务 (本地): docker-compose -f docker-compose.local.yml --profile local up -d" echo " 启动服务 (生产): docker-compose -f docker-compose.prod.yml --profile prod up -d" echo "" } # 执行主函数 main