From 4223c6b8da2bbc17274536de027673762a854569 Mon Sep 17 00:00:00 2001 From: lzh Date: Mon, 23 Mar 2026 11:23:44 +0800 Subject: [PATCH] =?UTF-8?q?fix(ci):=20Docker=20=E6=9E=84=E5=BB=BA=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E2=80=94=20=E4=BF=AE=E5=A4=8D=20Maven=20=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E8=B6=85=E6=97=B6=E3=80=81=E5=90=AF=E7=94=A8=20BuildK?= =?UTF-8?q?it=E3=80=81=E4=BC=98=E5=8C=96=E5=B1=82=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dockerfile.deps/template: 改用阿里云镜像手动安装 Maven,避免 apk maven 拉入冗余 openjdk25(600MB+)导致构建超时 - Jenkinsfile: 添加 DOCKER_BUILDKIT=1,使层缓存真正生效 - Dockerfile.deps: framework/dependencies 源码在 COPY . . 前单独复制并预编译, 提升缓存命中率;mvn install 去掉 || true,编译失败立即报错 - .dockerignore: 补充 .git/、docs/、sql/、scripts/ 等目录,构建上下文从 60MB 降至 ~5MB Co-Authored-By: Claude Opus 4.6 (1M context) --- .dockerignore | 67 ++++++++++--- Jenkinsfile | 3 + docker/Dockerfile.deps | 20 ++-- docker/Dockerfile.template | 190 +++++++++++++++++++------------------ 4 files changed, 165 insertions(+), 115 deletions(-) diff --git a/.dockerignore b/.dockerignore index e7e0a13..fb14b73 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,15 +1,52 @@ -target/ -.m2/ -*.log -*.tmp -.DS_Store -.idea/ -*.iml -.vscode/ -node_modules/ -dist/ -build/ -*.class -*.jar -!gradle-wrapper.jar -.gradle/ +# Git +.git/ +.gitignore + +# 构建产物 +**/target/ +.m2/ +*.class +*.jar +!gradle-wrapper.jar +.gradle/ + +# IDE +.idea/ +*.iml +*.iws +*.ipr +.vscode/ +.settings/ +.classpath +.project +.factorypath +.springBeans +.sts4-cache + +# 前端 +**/node_modules/ +dist/ +build/ + +# 文档与脚本(构建不需要) +docs/ +sql/ +scripts/ +openspec/ +AGENTS.md +CLAUDE.md +*.md +!**/pom.xml + +# AI / 工具目录 +.claude/ +.gstack/ +.qoder/ + +# 杂项 +*.log +*.tmp +.DS_Store +.history +.temp/ +coverage/ diff --git a/Jenkinsfile b/Jenkinsfile index ad39228..9e88007 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -17,6 +17,9 @@ pipeline { } environment { + // 启用 BuildKit(使层缓存、BUILDKIT_INLINE_CACHE 等特性真正生效) + DOCKER_BUILDKIT = '1' + // 镜像仓库配置(Infra 服务器内网地址,Prod 服务器可通过内网拉取) REGISTRY = '172.17.16.7:5000' DEPS_IMAGE = "${REGISTRY}/aiot-deps:latest" diff --git a/docker/Dockerfile.deps b/docker/Dockerfile.deps index 77763fc..a310996 100644 --- a/docker/Dockerfile.deps +++ b/docker/Dockerfile.deps @@ -5,8 +5,12 @@ FROM eclipse-temurin:17-jdk-alpine -# 安装 Maven -RUN apk add --no-cache maven +# 安装 Maven(从阿里云镜像下载,避免 apk maven 包拉入冗余 JDK) +ARG MAVEN_VERSION=3.9.9 +RUN wget -q https://mirrors.aliyun.com/apache/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz -O /tmp/maven.tar.gz \ + && tar xzf /tmp/maven.tar.gz -C /opt \ + && ln -s /opt/apache-maven-${MAVEN_VERSION}/bin/mvn /usr/bin/mvn \ + && rm /tmp/maven.tar.gz WORKDIR /build @@ -36,11 +40,13 @@ COPY viewsh-module-ops/viewsh-module-facilities-biz/pom.xml viewsh-module-ops/vi COPY viewsh-module-ops/viewsh-module-service-biz/pom.xml viewsh-module-ops/viewsh-module-service-biz/ COPY viewsh-module-ops/viewsh-module-ops-server/pom.xml viewsh-module-ops/viewsh-module-ops-server/ -# 下载所有依赖到本地仓库 +# 下载所有依赖到本地仓库(部分依赖可能无法离线解析,允许失败) RUN mvn dependency:go-offline -B || true -# 复制源代码 -COPY . . +# 先单独复制 framework 和 dependencies 源码并预编译(变动频率低,缓存命中率高) +COPY viewsh-dependencies/ viewsh-dependencies/ +COPY viewsh-framework/ viewsh-framework/ +RUN mvn install -pl viewsh-dependencies,viewsh-framework -am -DskipTests -B -q -# 预编译 framework 和 dependencies(所有服务共享) -RUN mvn install -pl viewsh-dependencies,viewsh-framework -am -DskipTests -B -q || true +# 最后复制全部源码(此层之后的缓存会随源码变动而失效) +COPY . . diff --git a/docker/Dockerfile.template b/docker/Dockerfile.template index d358688..f3cffdf 100644 --- a/docker/Dockerfile.template +++ b/docker/Dockerfile.template @@ -1,93 +1,97 @@ -# syntax=docker/dockerfile:1.4 - -# ============================================ -# 多阶段构建:Maven 编译 + 运行时镜像 -# 使用 Docker 层缓存加速构建 -# ============================================ - -# ============ 构建阶段 ============ -FROM eclipse-temurin:17-jdk-alpine AS builder - -# 安装 Maven -RUN apk add --no-cache maven - -WORKDIR /build - -# 构建参数 -ARG MODULE_NAME -ARG JAR_NAME -ARG SKIP_TESTS=true - -# 复制 pom 文件(利用 Docker 层缓存) -# 先复制 pom,再下载依赖,这样依赖层可以被缓存 -COPY pom.xml . -COPY viewsh-dependencies/pom.xml viewsh-dependencies/ -COPY viewsh-framework/pom.xml viewsh-framework/ -COPY viewsh-gateway/pom.xml viewsh-gateway/ -COPY viewsh-module-system/pom.xml viewsh-module-system/ -COPY viewsh-module-system/viewsh-module-system-api/pom.xml viewsh-module-system/viewsh-module-system-api/ -COPY viewsh-module-system/viewsh-module-system-server/pom.xml viewsh-module-system/viewsh-module-system-server/ -COPY viewsh-module-infra/pom.xml viewsh-module-infra/ -COPY viewsh-module-infra/viewsh-module-infra-api/pom.xml viewsh-module-infra/viewsh-module-infra-api/ -COPY viewsh-module-infra/viewsh-module-infra-server/pom.xml viewsh-module-infra/viewsh-module-infra-server/ -COPY viewsh-module-iot/pom.xml viewsh-module-iot/ -COPY viewsh-module-iot/viewsh-module-iot-core/pom.xml viewsh-module-iot/viewsh-module-iot-core/ -COPY viewsh-module-iot/viewsh-module-iot-api/pom.xml viewsh-module-iot/viewsh-module-iot-api/ -COPY viewsh-module-iot/viewsh-module-iot-server/pom.xml viewsh-module-iot/viewsh-module-iot-server/ -COPY viewsh-module-iot/viewsh-module-iot-gateway/pom.xml viewsh-module-iot/viewsh-module-iot-gateway/ - -# 下载依赖(这一层会被缓存,除非 pom 文件变化) -RUN mvn dependency:go-offline -B -q || true - -# 复制源代码(代码变化不会影响依赖层的缓存) -COPY . . - -# 编译打包 -RUN mvn clean package -pl ${MODULE_NAME} -am -DskipTests=${SKIP_TESTS} -B -q - -# ============ 运行阶段 ============ -FROM eclipse-temurin:17-jre-alpine - -# 安装必要工具(用于健康检查) -RUN apk add --no-cache wget curl - -# 构建参数 -ARG MODULE_NAME -ARG JAR_NAME -ARG APP_PORT=48080 - -# 元数据标签 -LABEL maintainer="XW-AIOT Team" -LABEL service="${MODULE_NAME}" - -# 创建非 root 用户 -RUN addgroup -g 1000 appuser && \ - adduser -D -u 1000 -G appuser appuser - -# 创建应用目录 -RUN mkdir -p /app/logs /app/config && \ - chown -R appuser:appuser /app - -WORKDIR /app - -# 从构建阶段复制 JAR 文件 -COPY --from=builder --chown=appuser:appuser /build/${MODULE_NAME}/target/${JAR_NAME}.jar app.jar - -# 切换到非 root 用户 -USER appuser - -# 环境变量 -ENV TZ=Asia/Shanghai \ - JAVA_OPTS="-Xms256m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs/heap-dump.hprof" \ - SPRING_PROFILES_ACTIVE=prod \ - APP_ARGS="" - -# 暴露端口 -EXPOSE ${APP_PORT} - -# 健康检查 -HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:${APP_PORT}/actuator/health || exit 1 - -# 启动应用 -ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar ${APP_ARGS}"] +# syntax=docker/dockerfile:1.4 + +# ============================================ +# 多阶段构建:Maven 编译 + 运行时镜像 +# 使用 Docker 层缓存加速构建 +# ============================================ + +# ============ 构建阶段 ============ +FROM eclipse-temurin:17-jdk-alpine AS builder + +# 安装 Maven(从阿里云镜像下载,避免 apk maven 包拉入冗余 JDK) +ARG MAVEN_VERSION=3.9.9 +RUN wget -q https://mirrors.aliyun.com/apache/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz -O /tmp/maven.tar.gz \ + && tar xzf /tmp/maven.tar.gz -C /opt \ + && ln -s /opt/apache-maven-${MAVEN_VERSION}/bin/mvn /usr/bin/mvn \ + && rm /tmp/maven.tar.gz + +WORKDIR /build + +# 构建参数 +ARG MODULE_NAME +ARG JAR_NAME +ARG SKIP_TESTS=true + +# 复制 pom 文件(利用 Docker 层缓存) +# 先复制 pom,再下载依赖,这样依赖层可以被缓存 +COPY pom.xml . +COPY viewsh-dependencies/pom.xml viewsh-dependencies/ +COPY viewsh-framework/pom.xml viewsh-framework/ +COPY viewsh-gateway/pom.xml viewsh-gateway/ +COPY viewsh-module-system/pom.xml viewsh-module-system/ +COPY viewsh-module-system/viewsh-module-system-api/pom.xml viewsh-module-system/viewsh-module-system-api/ +COPY viewsh-module-system/viewsh-module-system-server/pom.xml viewsh-module-system/viewsh-module-system-server/ +COPY viewsh-module-infra/pom.xml viewsh-module-infra/ +COPY viewsh-module-infra/viewsh-module-infra-api/pom.xml viewsh-module-infra/viewsh-module-infra-api/ +COPY viewsh-module-infra/viewsh-module-infra-server/pom.xml viewsh-module-infra/viewsh-module-infra-server/ +COPY viewsh-module-iot/pom.xml viewsh-module-iot/ +COPY viewsh-module-iot/viewsh-module-iot-core/pom.xml viewsh-module-iot/viewsh-module-iot-core/ +COPY viewsh-module-iot/viewsh-module-iot-api/pom.xml viewsh-module-iot/viewsh-module-iot-api/ +COPY viewsh-module-iot/viewsh-module-iot-server/pom.xml viewsh-module-iot/viewsh-module-iot-server/ +COPY viewsh-module-iot/viewsh-module-iot-gateway/pom.xml viewsh-module-iot/viewsh-module-iot-gateway/ + +# 下载依赖(这一层会被缓存,除非 pom 文件变化) +RUN mvn dependency:go-offline -B -q || true + +# 复制源代码(代码变化不会影响依赖层的缓存) +COPY . . + +# 编译打包 +RUN mvn clean package -pl ${MODULE_NAME} -am -DskipTests=${SKIP_TESTS} -B -q + +# ============ 运行阶段 ============ +FROM eclipse-temurin:17-jre-alpine + +# 安装必要工具(用于健康检查) +RUN apk add --no-cache wget curl + +# 构建参数 +ARG MODULE_NAME +ARG JAR_NAME +ARG APP_PORT=48080 + +# 元数据标签 +LABEL maintainer="XW-AIOT Team" +LABEL service="${MODULE_NAME}" + +# 创建非 root 用户 +RUN addgroup -g 1000 appuser && \ + adduser -D -u 1000 -G appuser appuser + +# 创建应用目录 +RUN mkdir -p /app/logs /app/config && \ + chown -R appuser:appuser /app + +WORKDIR /app + +# 从构建阶段复制 JAR 文件 +COPY --from=builder --chown=appuser:appuser /build/${MODULE_NAME}/target/${JAR_NAME}.jar app.jar + +# 切换到非 root 用户 +USER appuser + +# 环境变量 +ENV TZ=Asia/Shanghai \ + JAVA_OPTS="-Xms256m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs/heap-dump.hprof" \ + SPRING_PROFILES_ACTIVE=prod \ + APP_ARGS="" + +# 暴露端口 +EXPOSE ${APP_PORT} + +# 健康检查 +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:${APP_PORT}/actuator/health || exit 1 + +# 启动应用 +ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar ${APP_ARGS}"]