From 97dddf01a78691ae3661849f1846d75954d59573 Mon Sep 17 00:00:00 2001 From: lijiahangmax Date: Sat, 5 Jul 2025 23:43:46 +0800 Subject: [PATCH] =?UTF-8?q?:whale:=20=E4=BF=AE=E6=94=B9=20docker=20?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E9=80=BB=E8=BE=91.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/build.sh | 289 ------------------ .../Dockerfile.service} | 14 +- .../Dockerfile.ui} | 6 +- .../maven-settings.xml} | 11 + docker/docker-build.sh | 207 +++++++++++++ docker/project-build.sh | 125 ++++++++ .../dromara/visor/launch/ReplaceVersion.java | 3 +- 7 files changed, 355 insertions(+), 300 deletions(-) delete mode 100644 docker/build.sh rename docker/{service/Builder.Dockerfile => builder/Dockerfile.service} (57%) rename docker/{ui/Builder.Dockerfile => builder/Dockerfile.ui} (81%) rename docker/{service/settings.xml => builder/maven-settings.xml} (77%) create mode 100644 docker/docker-build.sh create mode 100644 docker/project-build.sh diff --git a/docker/build.sh b/docker/build.sh deleted file mode 100644 index fe8bacaa..00000000 --- a/docker/build.sh +++ /dev/null @@ -1,289 +0,0 @@ -#!/bin/bash -set -e - -# 版本号 -version=2.4.1 -# 是否推送镜像 -push_images=false -# 是否本地构建 -locally_build=false -# 是否预构建 service -pre_build_service=false -# 是否预构建 ui -pre_build_ui=false -# 备份后缀 -backup_suffix=".bak" -# 镜像命名空间 -namespace="registry.cn-hangzhou.aliyuncs.com/orionsec" - -# 解析命令行参数 -while [[ $# -gt 0 ]]; do - case "$1" in - -p|--push) - push_images=true - shift - ;; - -l|--locally) - locally_build=true - shift - ;; - -pre-service|--prebuild-service) - pre_build_service=true - shift - ;; - -pre-ui|--prebuild-ui) - pre_build_ui=true - shift - ;; - *) - echo "未知参数: $1" - exit 1 - ;; - esac -done - -# 要处理的 Dockerfile 列表及对应的镜像名称 -declare -A images=( - ["./ui/Dockerfile"]="orion-visor-ui" - ["./service/Dockerfile"]="orion-visor-service" - ["./mysql/Dockerfile"]="orion-visor-mysql" - ["./redis/Dockerfile"]="orion-visor-redis" - ["./adminer/Dockerfile"]="orion-visor-adminer" - ["./guacd/Dockerfile"]="orion-visor-guacd" -) - -# 准备 service app.jar -function prepare_app_jar() { - local source_file="../orion-visor-launch/target/orion-visor-launch.jar" - local target_file="./service/app.jar" - if [ ! -f "$target_file" ]; then - echo "警告: $target_file 不存在, 正在尝试从 $source_file 复制..." - if [ -f "$source_file" ]; then - cp "$source_file" "$target_file" - echo "✅ 已成功复制 $source_file 至 $target_file" - else - echo "❌ 错误: $source_file 不存在, 无法继续构建." - exit 1 - fi - else - echo "✅ $target_file 已存在, 无需复制." - fi -} - -# 准备前端 dist 目录 -function prepare_dist_directory() { - local source_dir="../orion-visor-ui/dist" - local target_dir="./ui/dist" - if [ ! -d "$target_dir" ]; then - echo "警告: $target_dir 不存在, 正在尝试从 $source_dir 复制..." - if [ -d "$source_dir" ]; then - cp -r "$source_dir" "$target_dir" - echo "✅ 已成功复制 $source_dir 至 $target_dir" - else - echo "❌ 错误: $source_dir 不存在, 无法继续构建." - exit 1 - fi - else - echo "✅ $target_dir 已存在, 无需复制." - fi -} - -# 准备 mysql sql 目录 -function prepare_sql_directory() { - local source_dir="../sql" - local target_dir="./mysql/sql" - if [ ! -d "$target_dir" ]; then - echo "警告: $target_dir 不存在, 正在尝试从 $source_dir 复制..." - if [ -d $source_dir ]; then - cp -r $source_dir "$target_dir" - echo "✅ 已成功复制 ../sql 至 $target_dir" - else - echo "❌ 错误: $source_dir 不存在!根据预期它应该存在, 请确认路径或项目结构是否正确。" - exit 1 - fi - else - echo "✅ $target_dir 已存在, 无需复制." - fi -} - -# 修改 Dockerfile 前的备份 -function modify_dockerfiles() { - if [ "$locally_build" = true ]; then - echo "跳过 Dockerfile 修改" - return - fi - for file in "${!images[@]}"; do - if [ -f "$file" ]; then - echo "备份并修改: $file" - cp "$file" "$file$backup_suffix" - sed -i 's/--platform=\$BUILDPLATFORM//g' "$file" - else - echo "文件不存在 -> $file" - fi - done -} - -# 恢复原始 Dockerfile -function restore_dockerfiles() { - if [ "$locally_build" = true ]; then - return - fi - for file in "${!images[@]}"; do - if [ -f "$file$backup_suffix" ]; then - echo "恢复: $file" - rm -rf "$file" - mv "$file$backup_suffix" "$file" - fi - done -} - -# 构建镜像 -function build_images() { - for dockerfile in "${!images[@]}"; do - image_name="${images[$dockerfile]}" - echo "Building $image_name with version $version and latest tag." - docker build -f "$dockerfile" \ - -t "${image_name}:${version}" \ - -t "${image_name}:latest" \ - -t "${namespace}/${image_name}:${version}" \ - -t "${namespace}/${image_name}:latest" . - done -} - -# 推送镜像 -function push_images_to_registry() { - if [ "$push_images" = true ]; then - echo "📤 正在推送镜像..." - for image_name in "${images[@]}"; do - docker push "${namespace}/${image_name}:${version}" - docker push "${namespace}/${image_name}:latest" - done - fi -} - -# 执行预构建 service -function run_prebuild_service() { - if [ "$pre_build_service" = false ]; then - return - fi - echo "🛠️ 开始执行 service 预构建流程..." - - local builder_dockerfile="./service/Builder.Dockerfile" - local builder_image="orion-visor-service-builder" - local builder_container="orion-visor-service-prebuilder" - local target_dir="../orion-visor-launch/target" - local target_jar="$target_dir/orion-visor-launch.jar" - - # 确保目标目录存在 - if [ ! -d "$target_dir" ]; then - echo "📁 创建目标目录: $target_dir" - mkdir -p "$target_dir" - else - # 如果 jar 已存在, 先删除 - if [ -f "$target_jar" ]; then - echo "🗑️ 删除已有文件: $target_jar" - rm -f "$target_jar" - fi - fi - - # 清理旧容器 - local container_id=$(docker ps -a -f "name=$builder_container" --format "{{.ID}}") - if [ -n "$container_id" ]; then - echo "🧹 删除旧容器: $builder_container" - docker rm -f "$container_id" - fi - - # 构建预构建镜像 - echo "🏗️ 正在构建预构建镜像..." - docker build \ - -f "$builder_dockerfile" \ - -t "$builder_image" . - - # 创建一个临时容器用于拷贝文件 - echo "📁 创建临时容器以提取 jar 文件..." - docker create --name "$builder_container" "$builder_image" > /dev/null - - # 拷贝构建好的 jar 文件到目标路径 - echo "📂 正在从容器中拷贝 jar 文件..." - docker cp "$builder_container":/build/target/orion-visor-launch.jar "$target_jar" - - # 清理临时容器 - docker rm -f "$builder_container" > /dev/null - echo "✅ 后端预构建完成, jar 文件已保存至: $target_jar" -} - -# 执行预构建 ui -function run_prebuild_ui() { - if [ "$pre_build_ui" = false ]; then - return - fi - echo "🛠️ 开始执行 ui 预构建流程..." - - local builder_dockerfile="./ui/Builder.Dockerfile" - local builder_image="orion-visor-ui-builder" - local builder_container="orion-visor-ui-prebuilder" - local target_dir="../orion-visor-ui/dist" - - # 如果 dist 已存在, 先删除 - if [ -d "$target_dir" ]; then - echo "🗑️ 删除已有目录: $target_dir" - rm -rf "$target_dir" - fi - - # 清理旧容器 - local container_id=$(docker ps -a -f "name=$builder_container" --format "{{.ID}}") - if [ -n "$container_id" ]; then - echo "🧹 删除旧容器: $builder_container" - docker rm -f "$container_id" - fi - - # 构建前端镜像 - echo "🏗️ 正在构建前端预构建镜像..." - docker build \ - -f "$builder_dockerfile" \ - -t "$builder_image" . - - # 创建临时容器用于拷贝文件 - echo "📁 创建临时容器以提取 dist 文件..." - docker create --name "$builder_container" "$builder_image" > /dev/null - - # 拷贝 dist 目录 - echo "📂 正在从容器中拷贝 dist 文件..." - docker cp "$builder_container":/app/dist "$target_dir" - - # 清理临时容器 - docker rm "$builder_container" > /dev/null - - echo "✅ 前端预构建完成, dist 已保存至: $target_dir" -} - -# 预构建 -run_prebuild_service -run_prebuild_ui - -# 检查资源 -echo "🔍 正在检查并准备必要的构建资源..." -prepare_app_jar -prepare_dist_directory -prepare_sql_directory -echo "✅ 所有前置资源已准备完毕。" - -# 修改镜像文件 -echo "✅ 正在备份并修改 Dockerfile..." -modify_dockerfiles - -# 设置异常捕获, 确保失败时恢复 Dockerfile -trap 'restore_dockerfiles; echo "❌ 构建失败, 已恢复原始 Dockerfile"; exit 1' ERR INT - -# 构建镜像 -echo "🏗️ 正在构建镜像..." -build_images - -# 推送镜像 -echo "📦 正在推送镜像..." -push_images_to_registry - -# 恢复原始 Dockerfile -restore_dockerfiles -trap - ERR INT -echo "✅ 构建完成, Dockerfile 已恢复为原始版本" \ No newline at end of file diff --git a/docker/service/Builder.Dockerfile b/docker/builder/Dockerfile.service similarity index 57% rename from docker/service/Builder.Dockerfile rename to docker/builder/Dockerfile.service index 50b1e753..3ca3d34e 100644 --- a/docker/service/Builder.Dockerfile +++ b/docker/builder/Dockerfile.service @@ -4,13 +4,13 @@ FROM maven:3.9.10-eclipse-temurin-8-alpine AS builder RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories # 拷贝 settings.xml -COPY ./service/settings.xml /root/.m2/ +COPY ./docker/builder/maven-settings.xml /root/.m2/settings.xml + +WORKDIR /build + +COPY . . # 复制 POM 文件先进行依赖下载 (利用 Docker 缓存) -WORKDIR /build -COPY ../pom.xml . -RUN mvn dependency:resolve - +RUN mvn dependency:go-offline --settings=/root/.m2/settings.xml # 构建 -COPY ../ . -RUN mvn clean package -DskipTests +RUN mvn clean package -DskipTests --settings=/root/.m2/settings.xml diff --git a/docker/ui/Builder.Dockerfile b/docker/builder/Dockerfile.ui similarity index 81% rename from docker/ui/Builder.Dockerfile rename to docker/builder/Dockerfile.ui index c439b52d..cc458006 100644 --- a/docker/ui/Builder.Dockerfile +++ b/docker/builder/Dockerfile.ui @@ -6,20 +6,20 @@ RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories # 安装 pnpm RUN corepack enable && corepack prepare pnpm@latest --activate -WORKDIR /app +WORKDIR /build # 设置 pnpm 使用指定的 registry ARG REGISTRY_URL=https://registry.npmmirror.com RUN pnpm config set registry $REGISTRY_URL # 复制项目文件 -COPY ../orion-visor-ui/package.json ./orion-visor-ui/pnpm-lock.yaml* ./ +COPY ./orion-visor-ui/package.json ./orion-visor-ui/pnpm-lock.yaml* ./ # 安装依赖 (利用 Docker 缓存层) RUN pnpm install --frozen-lockfile # 复制源代码 -COPY ../orion-visor-ui/ . +COPY ./orion-visor-ui/ . # 构建项目 RUN pnpm build diff --git a/docker/service/settings.xml b/docker/builder/maven-settings.xml similarity index 77% rename from docker/service/settings.xml rename to docker/builder/maven-settings.xml index b79392eb..11432b16 100644 --- a/docker/service/settings.xml +++ b/docker/builder/maven-settings.xml @@ -32,6 +32,17 @@ + + + + aliyun-plugin + https://maven.aliyun.com/repository/public + + + central-plugin + https://repo.maven.apache.org/maven2 + + diff --git a/docker/docker-build.sh b/docker/docker-build.sh new file mode 100644 index 00000000..a1d5e6fa --- /dev/null +++ b/docker/docker-build.sh @@ -0,0 +1,207 @@ +#!/bin/bash +set -e + +# DockerContext: orion-visor/docker + +# 加载项目构建 +source ./project-build.sh "$@" + +# 版本号 +version=2.test +# 是否推送镜像 +push_image=false +# 是否构建 latest +latest_image=false +# 是否本地构建 +locally_build=false +# 备份后缀 +backup_suffix=".bak" +# 镜像命名空间 +namespace="registry.cn-hangzhou.aliyuncs.com/orionsec" + +# 解析命令行参数 +while [[ $# -gt 0 ]]; do + case "$1" in + -l|--locally) + locally_build=true + shift + ;; + -latest|latest-image) + latest_image=true + shift + ;; + -push|--push-image) + push_image=true + shift + ;; + *) + shift + ;; + esac +done + +# 要处理的 Dockerfile 列表及对应的镜像名称 +declare -A images=( + ["./ui/Dockerfile"]="orion-visor-ui" + ["./service/Dockerfile"]="orion-visor-service" + ["./mysql/Dockerfile"]="orion-visor-mysql" + ["./redis/Dockerfile"]="orion-visor-redis" + ["./adminer/Dockerfile"]="orion-visor-adminer" + ["./guacd/Dockerfile"]="orion-visor-guacd" +) + +# 准备 service jar +function prepare_app_jar() { + local source_file="../orion-visor-launch/target/orion-visor-launch.jar" + local target_file="./service/orion-visor-launch.jar" + if [ ! -f "$target_file" ]; then + echo "警告: $target_file 不存在, 正在尝试从 $source_file 复制..." + if [ -f "$source_file" ]; then + cp "$source_file" "$target_file" + echo "已成功复制 $source_file 至 $target_file" + else + echo "错误: $source_file 不存在, 无法继续构建." + exit 1 + fi + else + echo "$target_file 已存在, 无需复制." + fi +} + +# 准备前端 dist 目录 +function prepare_dist_directory() { + local source_dir="../orion-visor-ui/dist" + local target_dir="./ui/dist" + if [ ! -d "$target_dir" ]; then + echo "警告: $target_dir 不存在, 正在尝试从 $source_dir 复制..." + if [ -d "$source_dir" ]; then + cp -r "$source_dir" "$target_dir" + echo "已成功复制 $source_dir 至 $target_dir" + else + echo "错误: $source_dir 不存在, 无法继续构建." + exit 1 + fi + else + echo "$target_dir 已存在, 无需复制." + fi +} + +# 准备 mysql sql 目录 +function prepare_sql_directory() { + local source_dir="../sql" + local target_dir="./mysql/sql" + if [ ! -d "$target_dir" ]; then + echo "警告: $target_dir 不存在, 正在尝试从 $source_dir 复制..." + if [ -d $source_dir ]; then + cp -r $source_dir "$target_dir" + echo "已成功复制 ../sql 至 $target_dir" + else + echo "错误: $source_dir 不存在!根据预期它应该存在, 请确认路径或项目结构是否正确" + exit 1 + fi + else + echo "$target_dir 已存在, 无需复制." + fi +} + +# 修改 Dockerfile 前的备份 +function modify_dockerfiles() { + if [ "$locally_build" = false ]; then + echo "跳过 Dockerfile 修改" + return + fi + echo "正在备份并修改 Dockerfile..." + for file in "${!images[@]}"; do + if [ -f "$file" ]; then + echo "备份并修改: $file" + cp "$file" "$file$backup_suffix" + sed -i 's/--platform=\$BUILDPLATFORM//g' "$file" + else + echo "文件不存在 -> $file" + fi + done +} + +# 恢复原始 Dockerfile +function restore_dockerfiles() { + if [ "$locally_build" = false ]; then + return + fi + echo "开始恢复 Dockerfile" + for file in "${!images[@]}"; do + if [ -f "$file$backup_suffix" ]; then + echo "恢复: $file" + rm -rf "$file" + mv "$file$backup_suffix" "$file" + fi + done + echo "Dockerfile 已恢复为原始版本" +} + +# 构建镜像 +function build_images() { + echo "构建镜像开始..." + for dockerfile in "${!images[@]}"; do + image_name="${images[$dockerfile]}" + echo "Building $image_name with version $version." + # 构建 Docker 镜像 + docker build -f "$dockerfile" -t "${image_name}:${version}" -t "${namespace}/${image_name}:${version}" . + # 添加 latest 标签 + if [ "$latest_image" = true ]; then + echo "Tag $image_name with latest version." + docker tag "${image_name}:${version}" "${image_name}:latest" + docker tag "${namespace}/${image_name}:${version}" "${namespace}/${image_name}:latest" + fi + done + echo "构建镜像结束..." +} + +# 推送镜像 +function push_image_to_registry() { + if [ "$push_image" = true ]; then + echo "推送镜像开始..." + for image_name in "${images[@]}"; do + # 推送版本 + docker push "${namespace}/${image_name}:${version}" + # 推送 latest + if [ "latest_image" = true ]; then + docker push "${namespace}/${image_name}:latest" + fi + done + echo "推送镜像结束..." + fi +} + +# 构建项目-service +if [ "$build_service" = true ]; then + run_build_service +fi + +# 构建项目-ui +if [ "$build_ui" = true ]; then + run_build_ui +fi + +# 检查资源 +echo "正在检查并准备必要的构建资源..." +prepare_app_jar +prepare_dist_directory +prepare_sql_directory +echo "所有前置资源已准备完毕" + +# 修改镜像文件 +modify_dockerfiles + +# 设置异常捕获, 确保失败时恢复 Dockerfile +trap 'restore_dockerfiles; echo "构建失败, 已恢复原始 Dockerfile"; exit 1' ERR INT + +# 构建镜像 +build_images + +# 推送镜像 +push_image_to_registry + +# 恢复原始 Dockerfile +restore_dockerfiles +trap - ERR INT +echo "构建完成" \ No newline at end of file diff --git a/docker/project-build.sh b/docker/project-build.sh new file mode 100644 index 00000000..d264304a --- /dev/null +++ b/docker/project-build.sh @@ -0,0 +1,125 @@ +#!/bin/bash +set -e + +# DockerContext: orion-visor + +# 版本号 +version=2.test +# 是否构建 service +export build_service=false +# 是否构建 ui +export build_ui=false + +# 解析命令行参数 +for arg in "$@"; do + case "$arg" in + -service|--build-service) + export build_service=true + ;; + -ui|--build-ui) + export build_ui=true + ;; + esac +done + +# 执行构建 service +function run_build_service() { + echo "开始执行 service 构建流程..." + + local builder_dockerfile="./builder/Dockerfile.service" + local builder_image="orion-visor-service-builder" + local builder_container="orion-visor-service-builder-ctn" + local builder_output="/build/orion-visor-launch/target/orion-visor-launch.jar" + local target_dir="../orion-visor-launch/target" + local target_jar="$target_dir/orion-visor-launch.jar" + + # 确保目标目录存在 + if [ ! -d "$target_dir" ]; then + echo "创建目标目录: $target_dir" + mkdir -p "$target_dir" + else + # 如果 jar 已存在, 先删除 + if [ -f "$target_jar" ]; then + echo "删除已有文件: $target_jar" + rm -f "$target_jar" + fi + fi + + # 清理旧容器 + local container_id=$(docker ps -a -f "name=$builder_container" --format "{{.ID}}") + if [ -n "$container_id" ]; then + echo "删除旧容器: $builder_container" + docker rm -f "$container_id" + fi + + # 构建构建镜像 + echo "正在构建 service builder image..." + docker build \ + -f "$builder_dockerfile" \ + -t "$builder_image:$version" ../ + + # 创建一个临时容器用于拷贝文件 + echo "创建临时容器以提取 jar 文件..." + docker create --name "$builder_container" "$builder_image:$version" > /dev/null + + # 拷贝构建好的 jar 文件到目标路径 + echo "正在从容器中拷贝 jar 文件..." + docker cp "$builder_container:$builder_output" "$target_jar" + + # 清理临时容器 + docker rm -f "$builder_container" > /dev/null + echo "后端构建完成, jar 文件已保存至: $target_jar" +} + +# 执行构建 ui +function run_build_ui() { + echo "开始执行 ui 构建流程..." + + local builder_dockerfile="./builder/Dockerfile.ui" + local builder_image="orion-visor-ui-builder" + local builder_container="orion-visor-ui-builder-ctn" + local builder_output="/build/dist" + local target_dir="../orion-visor-ui/dist" + + # 如果 dist 已存在, 先删除 + if [ -d "$target_dir" ]; then + echo "删除已有目录: $target_dir" + rm -rf "$target_dir" + fi + + # 清理旧容器 + local container_id=$(docker ps -a -f "name=$builder_container" --format "{{.ID}}") + if [ -n "$container_id" ]; then + echo "删除旧容器: $builder_container" + docker rm -f "$container_id" + fi + + # 构建前端镜像 + echo "正在构建 ui builder image..." + docker build \ + -f "$builder_dockerfile" \ + -t "$builder_image:$version" ../ + + # 创建临时容器用于拷贝文件 + echo "创建临时容器以提取 dist 文件..." + docker create --name "$builder_container" "$builder_image:$version" > /dev/null + + # 拷贝 dist 目录 + echo "正在从容器中拷贝 dist 文件..." + docker cp "$builder_container:$builder_output" "$target_dir" + + # 清理临时容器 + docker rm "$builder_container" > /dev/null + + echo "前端构建完成, dist 已保存至: $target_dir" +} + +# 构建项目-service +if [ "$build_service" = true ]; then + run_build_service +fi + +# 构建项目-ui +if [ "$build_ui" = true ]; then + run_build_ui +fi diff --git a/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java b/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java index ce19fec7..4be3d63b 100644 --- a/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java +++ b/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java @@ -46,7 +46,8 @@ public class ReplaceVersion { private static final String PATH = new File("").getAbsolutePath(); private static final String[] DOCKER_FILES = new String[]{ - "docker/build.sh", + "docker/docker-build.sh", + "docker/project-build.sh", "docker-compose.yml", "docker-compose-testing.yml" };