perf: 优化 CI Docker 镜像构建速度
- 新增 CI 精简 Dockerfile,直接打包 drone 预编译 jar,避免在 Docker 内重复编译(省去 npm ci + mvn 全量编译 ~15min) - build-docker-image 步骤改用精简 Dockerfile,去掉无效的 docker pull 缓存尝试 - maven-build 步骤优化:动态检测 CPU 核数设置并行度 -T 1C/2C、增加 JVM 内存、添加 --fail-at-end - .dockerignore 优化:CI Dockerfile 仅需 par-api/target/*.jar,排除所有源码/pom/前端文件 - par-api/Dockerfile 标注为独立多阶段构建版本(本地使用) 参考 mediabot 项目的多阶段构建思路,但将编译前置到 drone host 缓存中,Docker 构建秒级完成
This commit is contained in:
@@ -1,17 +1,20 @@
|
|||||||
# 构建产物
|
# 构建产物(jar 除外 — CI Dockerfile 需要拷贝 par-api/target/*.jar)
|
||||||
target/
|
|
||||||
*/target/
|
|
||||||
web/node_modules/
|
web/node_modules/
|
||||||
web/dist/
|
web/dist/
|
||||||
|
par-common/target/
|
||||||
|
par-core/target/
|
||||||
|
# 注意:不排除 par-api/target/,因为 CI Dockerfile 需要其中的 jar
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
.idea/
|
.idea/
|
||||||
*.iml
|
*.iml
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.codebuddy/
|
||||||
|
|
||||||
# Git
|
# Git
|
||||||
.git/
|
.git/
|
||||||
.gitignore
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
|
||||||
# 文档
|
# 文档
|
||||||
README.md
|
README.md
|
||||||
@@ -31,6 +34,22 @@ run.sh
|
|||||||
.drone.yml
|
.drone.yml
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
|
|
||||||
|
# 项目文件(Docker 上下文不需要)
|
||||||
|
pom.xml
|
||||||
|
par-*/pom.xml
|
||||||
|
|
||||||
|
# Java 源码(CI Dockerfile 不需要)
|
||||||
|
par-common/src/
|
||||||
|
par-core/src/
|
||||||
|
par-api/src/
|
||||||
|
|
||||||
|
# 前端源码(CI Dockerfile 不需要)
|
||||||
|
web/
|
||||||
|
|
||||||
# 其他
|
# 其他
|
||||||
*.md
|
*.md
|
||||||
*.log
|
*.log
|
||||||
|
*.iml
|
||||||
|
*.class
|
||||||
|
*.jar
|
||||||
|
!par-api/target/*.jar
|
||||||
|
|||||||
39
.drone.yml
39
.drone.yml
@@ -98,7 +98,7 @@ steps:
|
|||||||
image: 192.168.31.253/library/maven-java21:3.9.9-alpine
|
image: 192.168.31.253/library/maven-java21:3.9.9-alpine
|
||||||
pull: if-not-exists
|
pull: if-not-exists
|
||||||
environment:
|
environment:
|
||||||
MAVEN_OPTS: "-Dmaven.repo.local=/root/.m2/repository -Xms256m -Xmx512m"
|
MAVEN_OPTS: "-Dmaven.repo.local=/root/.m2/repository -Xms512m -Xmx1024m -Djava.awt.headless=true -Dmaven.compiler.forceJavacCompilerUse=true"
|
||||||
volumes:
|
volumes:
|
||||||
- name: maven-cache
|
- name: maven-cache
|
||||||
path: /root/.m2
|
path: /root/.m2
|
||||||
@@ -143,12 +143,24 @@ steps:
|
|||||||
echo "BUILD_DATE=$(TZ=Asia/Shanghai date +%Y%m%d)" >> /drone/src/.version.env
|
echo "BUILD_DATE=$(TZ=Asia/Shanghai date +%Y%m%d)" >> /drone/src/.version.env
|
||||||
echo "发布版本: $RELEASE_VERSION, 构建版本: $BUILD_VERSION"
|
echo "发布版本: $RELEASE_VERSION, 构建版本: $BUILD_VERSION"
|
||||||
|
|
||||||
# Maven 打包(使用阿里云镜像)
|
# 检测可用 CPU 核数,动态设置 Maven 并行度
|
||||||
|
CPU_CORES=$(nproc 2>/dev/null || echo 4)
|
||||||
|
echo "检测到 $CPU_CORES 个 CPU 核心"
|
||||||
|
if [ "$CPU_CORES" -ge 4 ]; then
|
||||||
|
MVN_THREADS="2C"
|
||||||
|
else
|
||||||
|
MVN_THREADS="1C"
|
||||||
|
fi
|
||||||
|
echo "Maven 并行度: -T $MVN_THREADS"
|
||||||
|
|
||||||
|
# Maven 打包(使用阿里云镜像 + 多线程并行编译 + 跳过测试 + 离线优先)
|
||||||
mvn -B clean package \
|
mvn -B clean package \
|
||||||
-s /root/.m2/settings.xml \
|
-s /root/.m2/settings.xml \
|
||||||
-DskipTests \
|
-DskipTests \
|
||||||
-T 1C \
|
-Dmaven.test.skip=true \
|
||||||
--no-transfer-progress
|
-T "$MVN_THREADS" \
|
||||||
|
--no-transfer-progress \
|
||||||
|
--fail-at-end
|
||||||
|
|
||||||
JAR_FILE=$(ls par-api/target/*.jar | head -1)
|
JAR_FILE=$(ls par-api/target/*.jar | head -1)
|
||||||
echo "构建成功!产物: $JAR_FILE ($(du -sh $JAR_FILE | cut -f1))"
|
echo "构建成功!产物: $JAR_FILE ($(du -sh $JAR_FILE | cut -f1))"
|
||||||
@@ -157,6 +169,8 @@ steps:
|
|||||||
- frontend-build
|
- frontend-build
|
||||||
|
|
||||||
# ===================== Docker 镜像构建 =====================
|
# ===================== Docker 镜像构建 =====================
|
||||||
|
# 参考 mediabot 优化:Drone 已在前序步骤完成编译(frontend-build + maven-build),
|
||||||
|
# 此处使用 CI 精简 Dockerfile,仅将预构建 jar 打包进 JRE 镜像,无需在 Docker 内重新编译。
|
||||||
- name: build-docker-image
|
- name: build-docker-image
|
||||||
image: 192.168.31.253/library/docker:cli
|
image: 192.168.31.253/library/docker:cli
|
||||||
volumes:
|
volumes:
|
||||||
@@ -176,21 +190,22 @@ steps:
|
|||||||
fi
|
fi
|
||||||
echo "版本: $APP_VERSION"
|
echo "版本: $APP_VERSION"
|
||||||
|
|
||||||
# 拉取之前的镜像作为缓存来源(加速 layer 复用)
|
# 验证 jar 产物存在
|
||||||
echo "正在拉取缓存镜像..."
|
JAR_FILE=$(ls par-api/target/*.jar 2>/dev/null | head -1)
|
||||||
docker pull "$IMAGE_NAME:latest" 2>/dev/null || true
|
if [ -z "$JAR_FILE" ]; then
|
||||||
docker pull "$LOCAL_HARBOR_REG/$LOCAL_HARBOR_PROJ/$IMAGE_NAME:latest" 2>/dev/null || true
|
echo "错误:未找到 jar 产物,maven-build 可能失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "jar 产物: $JAR_FILE ($(du -sh $JAR_FILE | cut -f1))"
|
||||||
|
|
||||||
# 使用 BuildKit 构建,启用缓存
|
# 使用 CI 精简 Dockerfile:仅 COPY jar + 设置运行环境,秒级完成
|
||||||
docker build \
|
docker build \
|
||||||
--cache-from "$IMAGE_NAME:latest" \
|
|
||||||
--cache-from "$LOCAL_HARBOR_REG/$LOCAL_HARBOR_PROJ/$IMAGE_NAME:latest" \
|
|
||||||
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
||||||
--build-arg VERSION="$APP_VERSION" \
|
--build-arg VERSION="$APP_VERSION" \
|
||||||
--build-arg BUILD_TIME="$(TZ=Asia/Shanghai date '+%Y-%m-%d %H:%M')" \
|
--build-arg BUILD_TIME="$(TZ=Asia/Shanghai date '+%Y-%m-%d %H:%M')" \
|
||||||
-t "$IMAGE_NAME:$BUILD_VERSION" \
|
-t "$IMAGE_NAME:$BUILD_VERSION" \
|
||||||
-t "$IMAGE_NAME:latest" \
|
-t "$IMAGE_NAME:latest" \
|
||||||
-f par-api/Dockerfile \
|
-f Dockerfile \
|
||||||
.
|
.
|
||||||
|
|
||||||
echo "Docker 镜像构建完成。"
|
echo "Docker 镜像构建完成。"
|
||||||
|
|||||||
38
Dockerfile
Normal file
38
Dockerfile
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
# PAR Server - CI 专用精简镜像
|
||||||
|
# 参考 mediabot 的优化思路:Drone 流水线已完成编译,此处仅打包产物
|
||||||
|
# 完整多阶段构建版本见 par-api/Dockerfile(适用于本地独立构建)
|
||||||
|
|
||||||
|
FROM 192.168.31.253/library/eclipse-temurin:21-jre-alpine
|
||||||
|
|
||||||
|
ARG VERSION=unknown
|
||||||
|
ARG BUILD_TIME=unknown
|
||||||
|
ARG BUILDKIT_INLINE_CACHE=1
|
||||||
|
|
||||||
|
LABEL maintainer="PAR Team"
|
||||||
|
LABEL description="PT Adapter Registry Server"
|
||||||
|
LABEL version="${VERSION}"
|
||||||
|
LABEL build-time="${BUILD_TIME}"
|
||||||
|
|
||||||
|
# 创建非 root 用户
|
||||||
|
RUN addgroup -S par && adduser -S par -G par
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 创建静态文件目录
|
||||||
|
RUN mkdir -p /app/static/configs && chown -R par:par /app
|
||||||
|
|
||||||
|
# 直接复制 drone 已构建好的 jar(无需在 Docker 内重新编译)
|
||||||
|
COPY par-api/target/*.jar app.jar
|
||||||
|
|
||||||
|
USER par
|
||||||
|
|
||||||
|
# 暴露端口
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# 健康检查
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
|
||||||
|
CMD wget -qO- http://localhost:8080/health || exit 1
|
||||||
|
|
||||||
|
# 启动参数
|
||||||
|
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
# PAR Server - 前后端一体化 Docker 镜像
|
# PAR Server - 前后端一体化 Docker 镜像(完整多阶段构建)
|
||||||
# 参考 mediabot 的多阶段构建方式
|
# 参考 mediabot 的多阶段构建方式,适用于本地独立构建(不依赖 Drone CI 预编译)
|
||||||
|
# CI 流水线请使用项目根目录的 Dockerfile(精简版,仅打包 drone 预编译产物)
|
||||||
# 启用 BuildKit 以支持 cache mount
|
# 启用 BuildKit 以支持 cache mount
|
||||||
|
|
||||||
# 第一阶段:构建前端
|
# 第一阶段:构建前端
|
||||||
|
|||||||
Reference in New Issue
Block a user