Files
urbanLifeline/docker/build.sh

382 lines
10 KiB
Bash
Raw Permalink Normal View History

2025-12-28 18:30:17 +08:00
#!/bin/bash
##############################################
# Urban Lifeline - 构建和打包脚本
#
# 功能:
# 1. 编译后端/前端项目
# 2. 构建 Docker 镜像
# 3. 导出镜像到 tar 文件
#
# 使用方法:
# ./build.sh [target] [options]
#
# 目标(target)
# base - 构建基础镜像
# serv - 构建所有后端服务镜像
# web - 构建前端镜像
# all - 构建所有镜像(默认)
# gateway - 构建单个后端服务
# system/auth/file/ai/workcase - 同上
#
# 选项(options)
# compile - 先编译代码再构建镜像
# save - 构建后导出镜像到 tar 文件
# save=VERSION - 导出指定版本的镜像
#
# 示例:
# ./build.sh all compile save # 编译+构建+导出所有
# ./build.sh gateway compile # 编译+构建 gateway
# ./build.sh serv save # 构建+导出所有后端
# ./build.sh web compile save # 编译+构建+导出前端
##############################################
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
# 项目路径
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
PROJECT_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
DOCKER_DIR="${SCRIPT_DIR}"
BUILD_OUTPUT="${DOCKER_DIR}/output"
IMAGE_VERSION=$(date +%Y%m%d_%H%M%S)
# 服务列表
SERV_SERVICES="gateway system auth file ai workcase"
# 服务端口映射
declare -A SERVICE_PORTS=(
["gateway"]=8080
["system"]=8082
["auth"]=8081
["file"]=8084
["ai"]=8090
["workcase"]=8088
)
# 解析参数
BUILD_TARGET="${1:-all}"
shift || true
DO_COMPILE=false
DO_SAVE=false
SAVE_VERSION=""
for arg in "$@"; do
case $arg in
compile)
DO_COMPILE=true
;;
save)
DO_SAVE=true
;;
save=*)
DO_SAVE=true
SAVE_VERSION="${arg#save=}"
;;
esac
done
# 确定保存版本
if [ "${DO_SAVE}" = true ] && [ -z "${SAVE_VERSION}" ]; then
SAVE_VERSION="${IMAGE_VERSION}"
fi
echo "=========================================="
echo "Urban Lifeline - 构建脚本"
echo "=========================================="
log_info "构建目标: ${BUILD_TARGET}"
log_info "构建版本: ${IMAGE_VERSION}"
log_info "编译代码: ${DO_COMPILE}"
log_info "保存镜像: ${DO_SAVE}"
[ "${DO_SAVE}" = true ] && log_info "保存版本: ${SAVE_VERSION}"
echo "=========================================="
echo ""
mkdir -p "${BUILD_OUTPUT}"
# ================================================
# 编译函数
# ================================================
compile_serv_all() {
log_step "编译所有后端服务"
cd "${PROJECT_ROOT}/urbanLifelineServ"
mvn clean package -DskipTests
log_info "✅ 后端服务编译完成"
}
compile_serv_single() {
local service=$1
log_step "编译 ${service} 服务"
cd "${PROJECT_ROOT}/urbanLifelineServ"
mvn clean package -DskipTests -pl ${service} -am
log_info "${service} 服务编译完成"
}
compile_web() {
log_step "编译前端项目"
cd "${PROJECT_ROOT}/urbanLifelineWeb"
# 检查 pnpm
if command -v pnpm &> /dev/null; then
pnpm install
pnpm run build:all 2>/dev/null || {
# 如果没有 build:all 脚本,分别构建
log_info "分别构建各前端项目..."
cd packages/shared && pnpm run build && cd ../..
cd packages/platform && pnpm run build && cd ../..
cd packages/workcase && pnpm run build && cd ../..
}
else
npm install
npm run build:all 2>/dev/null || {
cd packages/shared && npm run build && cd ../..
cd packages/platform && npm run build && cd ../..
cd packages/workcase && npm run build && cd ../..
}
fi
log_info "✅ 前端项目编译完成"
}
# ================================================
# 构建函数
# ================================================
build_base() {
log_step "构建基础镜像"
cd "${PROJECT_ROOT}"
docker build \
-t urban-lifeline-base-serv:${IMAGE_VERSION} \
-t urban-lifeline-base-serv:latest \
-f docker/urbanLifeline/serv/Dockerfile.base .
log_info "✅ 基础镜像构建完成: urban-lifeline-base-serv:${IMAGE_VERSION}"
}
build_serv_single() {
local service=$1
local port=${SERVICE_PORTS[$service]}
log_step "构建 ${service} 服务镜像"
# 检查 JAR 包
local jar_file=$(find "${PROJECT_ROOT}/urbanLifelineServ/${service}/target" -name "*.jar" -type f 2>/dev/null | head -1)
if [ -z "$jar_file" ]; then
log_error "JAR 包不存在,请先编译: ./build.sh ${service} compile"
exit 1
fi
cd "${PROJECT_ROOT}"
docker build \
--build-arg SERVICE_NAME=${service} \
--build-arg SERVICE_PORT=${port} \
-t urban-lifeline-${service}:${IMAGE_VERSION} \
-t urban-lifeline-${service}:latest \
-f docker/urbanLifeline/serv/Dockerfile.template .
log_info "${service} 镜像构建完成: urban-lifeline-${service}:${IMAGE_VERSION}"
}
build_serv_all() {
for service in ${SERV_SERVICES}; do
build_serv_single ${service}
done
log_info "✅ 所有后端服务镜像构建完成"
}
build_web() {
build_platform
build_workcase_web
log_info "✅ 所有前端镜像构建完成"
}
build_platform() {
log_step "构建 platform 镜像"
if [ ! -d "${PROJECT_ROOT}/urbanLifelineWeb/packages/platform/dist" ]; then
log_error "platform dist 不存在,请先编译: ./build.sh platform compile"
exit 1
fi
cd "${PROJECT_ROOT}"
docker build \
--build-arg WEB_NAME=platform \
-t urban-lifeline-platform:${IMAGE_VERSION} \
-t urban-lifeline-platform:latest \
-f docker/urbanLifeline/web/Dockerfile .
log_info "✅ platform 镜像构建完成: urban-lifeline-platform:${IMAGE_VERSION}"
}
build_workcase_web() {
log_step "构建 workcase-web 镜像"
if [ ! -d "${PROJECT_ROOT}/urbanLifelineWeb/packages/workcase/dist" ]; then
log_error "workcase dist 不存在,请先编译: ./build.sh workcase-web compile"
exit 1
fi
cd "${PROJECT_ROOT}"
docker build \
--build-arg WEB_NAME=workcase \
-t urban-lifeline-workcase-web:${IMAGE_VERSION} \
-t urban-lifeline-workcase-web:latest \
-f docker/urbanLifeline/web/Dockerfile .
log_info "✅ workcase-web 镜像构建完成: urban-lifeline-workcase-web:${IMAGE_VERSION}"
}
# ================================================
# 导出函数
# ================================================
save_image() {
local image_name=$1
local version=${SAVE_VERSION}
local output_file="${BUILD_OUTPUT}/${image_name}_${version}.tar"
log_info "导出镜像: ${image_name}:${version}"
if ! docker images | grep -q "${image_name}.*${version}"; then
log_error "镜像不存在: ${image_name}:${version}"
return 1
fi
docker save -o "${output_file}" ${image_name}:${version}
local size=$(du -h "${output_file}" | cut -f1)
log_info "✅ 镜像已导出: ${output_file} (${size})"
}
save_serv_all() {
for service in ${SERV_SERVICES}; do
save_image "urban-lifeline-${service}"
done
}
# ================================================
# 主流程
# ================================================
main() {
# 编译
if [ "${DO_COMPILE}" = true ]; then
case ${BUILD_TARGET} in
base)
# 基础镜像不需要编译
;;
serv)
compile_serv_all
;;
web)
compile_web
;;
all)
compile_serv_all
compile_web
;;
gateway|system|auth|file|ai|workcase)
compile_serv_single ${BUILD_TARGET}
;;
*)
log_error "未知目标: ${BUILD_TARGET}"
exit 1
;;
esac
fi
# 构建镜像
case ${BUILD_TARGET} in
base)
build_base
;;
serv)
build_serv_all
;;
web)
build_web
;;
platform)
build_platform
;;
workcase-web)
build_workcase_web
;;
all)
# 检查基础镜像
if ! docker images | grep -q "urban-lifeline-base-serv.*latest"; then
log_warn "基础镜像不存在,先构建基础镜像"
build_base
fi
build_serv_all
build_web
;;
gateway|system|auth|file|ai|workcase)
build_serv_single ${BUILD_TARGET}
;;
*)
log_error "未知目标: ${BUILD_TARGET}"
echo ""
echo "可用目标: base, serv, web, all, gateway, system, auth, file, ai, workcase, platform, workcase-web"
exit 1
;;
esac
# 导出镜像
if [ "${DO_SAVE}" = true ]; then
case ${BUILD_TARGET} in
base)
save_image "urban-lifeline-base-serv"
;;
serv)
save_serv_all
;;
web)
save_image "urban-lifeline-platform"
save_image "urban-lifeline-workcase-web"
;;
platform)
save_image "urban-lifeline-platform"
;;
workcase-web)
save_image "urban-lifeline-workcase-web"
;;
all)
save_image "urban-lifeline-base-serv"
save_serv_all
save_image "urban-lifeline-platform"
save_image "urban-lifeline-workcase-web"
;;
gateway|system|auth|file|ai|workcase)
save_image "urban-lifeline-${BUILD_TARGET}"
;;
esac
echo ""
log_info "导出文件列表:"
ls -lh "${BUILD_OUTPUT}"/*.tar 2>/dev/null || true
fi
# 显示镜像列表
echo ""
log_info "Docker 镜像列表:"
docker images | grep "urban-lifeline" | head -20
echo ""
echo "=========================================="
log_info "✅ 构建完成!"
echo "=========================================="
}
main