265 lines
9.1 KiB
Bash
Executable File
265 lines
9.1 KiB
Bash
Executable File
#!/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 <env> 使用配置文件 (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
|