From 65771f0b4163cf9fce12070243ec12ae3878812d Mon Sep 17 00:00:00 2001 From: lijiahangmax Date: Sat, 5 Jul 2025 17:44:33 +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 --- .github/workflows/docker-publish.yml | 34 ++- docker-build.sh | 40 --- docker/build.sh | 289 ++++++++++++++++++ docker/mysql/Dockerfile | 6 +- docker/redis/Dockerfile | 2 +- docker/service/Builder.Dockerfile | 16 + docker/service/Dockerfile | 22 +- docker/ui/Builder.Dockerfile | 25 ++ docker/ui/Dockerfile | 32 +- .../main/resources/mapper/DataExtraMapper.xml | 2 +- 10 files changed, 371 insertions(+), 97 deletions(-) delete mode 100644 docker-build.sh create mode 100644 docker/build.sh create mode 100644 docker/service/Builder.Dockerfile create mode 100644 docker/ui/Builder.Dockerfile diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 01398dc3..351cdd21 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -27,6 +27,36 @@ jobs: - name: 🌱 Checkout repository uses: actions/checkout@v4 + - name: ⚙️ Set up JDK 8 + uses: actions/setup-java@v4 + with: + java-version: '8' + distribution: 'temurin' + cache: 'maven' + + - name: ⚙️ Set up Node.js 18 + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: 🔧 Install pnpm + run: npm i -g pnpm + + - name: 📦 Build Java + run: mvn -U clean install -DskipTests + + - name: 📦️ Build UI + working-directory: ./orion-visor-ui + run: | + pnpm install + pnpm build + + - name: 📁 Prepare build context + run: | + cp -r ./sql ./docker/mysql + cp -r ./orion-visor-ui/dist ./docker/ui/dist + cp ./orion-visor-launch/target/orion-visor-launch.jar ./docker/service/orion-visor-launch.jar + - name: ⚙️ Set up QEMU uses: docker/setup-qemu-action@v3 @@ -67,7 +97,7 @@ jobs: - name: 🛠️ Build and push Docker image for orion-visor-${{ matrix.service }} uses: docker/build-push-action@v5 with: - context: . + context: ./docker file: ./docker/${{ matrix.service }}/Dockerfile push: true tags: | @@ -78,4 +108,4 @@ jobs: ${{ env.ALIYUN_REGISTRY }}/${{ env.ALIYUN_NAMESPACE }}/orion-visor-${{ matrix.service }}:${{ steps.meta.outputs.version }} ${{ env.ALIYUN_REGISTRY }}/${{ env.ALIYUN_NAMESPACE }}/orion-visor-${{ matrix.service }}:latest labels: ${{ steps.meta.outputs.labels }} - platforms: linux/amd64,linux/arm64 \ No newline at end of file + platforms: linux/amd64,linux/arm64 diff --git a/docker-build.sh b/docker-build.sh deleted file mode 100644 index 57a93baf..00000000 --- a/docker-build.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -set -e - -# 版本 -version=2.4.1 -# 是否推送 -push_images=false -# 命令空间 -namespace="registry.cn-hangzhou.aliyuncs.com/orionsec" - -# 解析参数 -while [[ $# -gt 0 ]]; do - case "$1" in - --push) - push_images=true - shift - ;; - *) - echo "未知参数: $1" - exit 1 - ;; - esac -done - -docker build -f ./docker/ui/Dockerfile -t orion-visor-ui:${version} -t ${namespace}/orion-visor-ui:${version} -t ${namespace}/orion-visor-ui:${version} . && \ -docker build -f ./docker/service/Dockerfile -t orion-visor-service:${version} -t ${namespace}/orion-visor-service:${version} -t ${namespace}/orion-visor-service:${version} . && \ -docker build -f ./docker/mysql/Dockerfile -t orion-visor-mysql:${version} -t ${namespace}/orion-visor-mysql:${version} -t ${namespace}/orion-visor-mysql:${version} . && \ -docker build -f ./docker/redis/Dockerfile -t orion-visor-redis:${version} -t ${namespace}/orion-visor-redis:${version} -t ${namespace}/orion-visor-redis:${version} . && \ -docker build -f ./docker/adminer/Dockerfile -t orion-visor-adminer:${version} -t ${namespace}/orion-visor-adminer:${version} -t ${namespace}/orion-visor-adminer:${version} . && \ -docker build -f ./docker/guacd/Dockerfile -t orion-visor-guacd:${version} -t ${namespace}/orion-visor-guacd:${version} -t ${namespace}/orion-visor-guacd:${version} . - -# 推送镜像 -if [ "$push_images" = true ]; then - docker push ${namespace}/orion-visor-adminer:${version} - docker push ${namespace}/orion-visor-mysql:${version} - docker push ${namespace}/orion-visor-redis:${version} - docker push ${namespace}/orion-visor-guacd:${version} - docker push ${namespace}/orion-visor-service:${version} - docker push ${namespace}/orion-visor-ui:${version} -fi diff --git a/docker/build.sh b/docker/build.sh new file mode 100644 index 00000000..fe8bacaa --- /dev/null +++ b/docker/build.sh @@ -0,0 +1,289 @@ +#!/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/mysql/Dockerfile b/docker/mysql/Dockerfile index 7b37afb9..185e2137 100644 --- a/docker/mysql/Dockerfile +++ b/docker/mysql/Dockerfile @@ -7,11 +7,11 @@ ARG TZ=Asia/Shanghai RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \ echo "${TZ}" > /etc/timezone -# 复制配置 -COPY ./docker/mysql/my.cnf /etc/mysql/conf.d/my.cnf +# 复制配置文件 +COPY ./mysql/my.cnf /etc/mysql/conf.d/my.cnf # 复制初始化脚本 -COPY ./sql /tmp +COPY ./mysql/sql /tmp # 设置初始化脚本 RUN cat /tmp/init-1-schema-databases.sql >> /tmp/init.sql && \ diff --git a/docker/redis/Dockerfile b/docker/redis/Dockerfile index 42947dc9..251240a3 100644 --- a/docker/redis/Dockerfile +++ b/docker/redis/Dockerfile @@ -16,7 +16,7 @@ RUN \ rm -f /usr/local/redis.conf # 复制配置文件 -COPY ./docker/redis/redis.conf /usr/local/redis.conf +COPY ./redis/redis.conf /usr/local/redis.conf # 启动 Redis 并加载自定义配置 CMD ["redis-server", "/usr/local/redis.conf"] \ No newline at end of file diff --git a/docker/service/Builder.Dockerfile b/docker/service/Builder.Dockerfile new file mode 100644 index 00000000..50b1e753 --- /dev/null +++ b/docker/service/Builder.Dockerfile @@ -0,0 +1,16 @@ +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/ + +# 复制 POM 文件先进行依赖下载 (利用 Docker 缓存) +WORKDIR /build +COPY ../pom.xml . +RUN mvn dependency:resolve + +# 构建 +COPY ../ . +RUN mvn clean package -DskipTests diff --git a/docker/service/Dockerfile b/docker/service/Dockerfile index 5f82c964..5bddabf8 100644 --- a/docker/service/Dockerfile +++ b/docker/service/Dockerfile @@ -1,21 +1,3 @@ -# 构建应用 -FROM --platform=$BUILDPLATFORM 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 ./docker/service/settings.xml /root/.m2/ - -# 复制 POM 文件先进行依赖下载 (利用 Docker 缓存) -WORKDIR /build -COPY pom.xml . -RUN mvn dependency:resolve - -# 构建 -COPY . . -RUN mvn clean package -DskipTests - FROM --platform=$BUILDPLATFORM openjdk:8-jdk-alpine USER root @@ -35,8 +17,8 @@ RUN \ ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \ echo "${TZ}" > /etc/timezone -# 从构建阶段复制 jar 包 -COPY --from=builder /build/orion-visor-launch/target/orion-visor-launch.jar /app/app.jar +# 复制 jar 包 +COPY ./service/orion-visor-launch.jar /app/app.jar # 启动 CMD ["java", "-jar", "/app/app.jar"] diff --git a/docker/ui/Builder.Dockerfile b/docker/ui/Builder.Dockerfile new file mode 100644 index 00000000..c439b52d --- /dev/null +++ b/docker/ui/Builder.Dockerfile @@ -0,0 +1,25 @@ +FROM node:18-alpine AS builder + +# 设置阿里云镜像加速 +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 + +# 设置 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* ./ + +# 安装依赖 (利用 Docker 缓存层) +RUN pnpm install --frozen-lockfile + +# 复制源代码 +COPY ../orion-visor-ui/ . + +# 构建项目 +RUN pnpm build diff --git a/docker/ui/Dockerfile b/docker/ui/Dockerfile index 9a93db56..ce02e252 100644 --- a/docker/ui/Dockerfile +++ b/docker/ui/Dockerfile @@ -1,31 +1,3 @@ -# 构建应用 -FROM --platform=$BUILDPLATFORM node:18-alpine AS builder - -# 设置阿里云镜像加速 -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 - -# 设置 pnpm 使用指定的 registry -ARG REGISTRY_URL=https://registry.npmmirror.com -RUN pnpm config set registry $REGISTRY_URL - -# 复制项目文件 (package.json等) -COPY ./orion-visor-ui/package.json ./orion-visor-ui/pnpm-lock.yaml* ./ - -# 安装依赖 (利用 Docker 缓存层) -RUN pnpm install --frozen-lockfile - -# 复制源代码 -COPY ./orion-visor-ui/ . - -# 构建项目 -RUN pnpm build - -# 打包静态资源 FROM --platform=$BUILDPLATFORM nginx:alpine # 系统时区 @@ -42,10 +14,10 @@ RUN \ rm -rf /etc/nginx/conf.d/* # 复制包 -COPY --from=builder /app/dist /usr/share/nginx/html +COPY ./ui/dist /usr/share/nginx/html # 复制配置 -COPY ./docker/ui/nginx.conf /etc/nginx/conf.d +COPY ./ui/nginx.conf /etc/nginx/conf.d # 启动 CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/mapper/DataExtraMapper.xml b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/mapper/DataExtraMapper.xml index fd6a0e7d..47c23387 100644 --- a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/mapper/DataExtraMapper.xml +++ b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/mapper/DataExtraMapper.xml @@ -60,7 +60,7 @@ ) WHERE deleted = 0 AND type = 'HOST' - AND item IN ('SSH', 'RDP') + AND item IN ('SSH', 'RDP', 'VNC') JSON_CONTAINS(value, JSON_OBJECT('identityId', #{item}))