diff --git a/Dockerfile b/Dockerfile index 423fe3e..02c14a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,25 @@ FROM --platform=linux/amd64 maven:3.9.9-eclipse-temurin-21 AS build ARG SERVICE_MODULE WORKDIR /workspace +# Copy only pom files first — layer cached until any pom.xml changes COPY pom.xml ./pom.xml COPY maven-settings.xml ./maven-settings.xml +COPY common/pom.xml ./common/pom.xml +COPY im-sdk/pom.xml ./im-sdk/pom.xml +COPY tenant-service/pom.xml ./tenant-service/pom.xml +COPY im-service/pom.xml ./im-service/pom.xml +COPY push-service/pom.xml ./push-service/pom.xml +COPY update-service/pom.xml ./update-service/pom.xml +COPY demo-service/pom.xml ./demo-service/pom.xml +COPY file-service/pom.xml ./file-service/pom.xml +COPY license-service/pom.xml ./license-service/pom.xml + +# Pre-download dependencies using BuildKit cache mount — persisted across builds +RUN --mount=type=cache,target=/root/.m2 \ + mvn -s /workspace/maven-settings.xml -pl ${SERVICE_MODULE} -am \ + dependency:go-offline -q + +# Copy source — invalidates only the compile layer, not the deps layer COPY common ./common COPY im-sdk ./im-sdk COPY tenant-service ./tenant-service @@ -16,9 +33,11 @@ COPY demo-service ./demo-service COPY file-service ./file-service COPY license-service ./license-service -RUN mvn -U -s /workspace/maven-settings.xml -pl ${SERVICE_MODULE} -am -DskipTests package +RUN --mount=type=cache,target=/root/.m2 \ + mvn -s /workspace/maven-settings.xml -pl ${SERVICE_MODULE} -am -DskipTests package -FROM --platform=linux/amd64 eclipse-temurin:21-jre-jammy +# Use Alpine-based JRE — ~100MB smaller than jammy +FROM --platform=linux/amd64 eclipse-temurin:21-jre-alpine WORKDIR /app ARG SERVICE_MODULE diff --git a/Jenkinsfile b/Jenkinsfile index 36d5d1f..97559be 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,28 +2,34 @@ pipeline { agent any parameters { - string(name: 'BRANCH', defaultValue: 'main', description: 'Git 分支名') choice(name: 'SERVICE', choices: ['tenant-service', 'im-service', 'push-service', 'update-service', 'demo-service', 'file-service', 'license-service'], description: '要构建的服务模块') string(name: 'IMAGE_TAG', defaultValue: 'latest', description: '镜像 Tag(如 v1.2.3 或 latest)') booleanParam(name: 'DEPLOY', defaultValue: true, description: '构建后是否自动部署到生产服务器') } environment { - ACR_REGISTRY = 'crpi-n44qjpuucgjt8e8c.cn-beijing.personal.cr.aliyuncs.com' - ACR_NAMESPACE = 'xuqmgroup' - ACR_USERNAME = 'xuqinmin12' - PROD_HOST = '106.54.23.149' - PROD_USER = 'ubuntu' - COMPOSE_FILE = '/opt/xuqm/deploy/compose.production.yaml' + ACR_REGISTRY = 'crpi-n44qjpuucgjt8e8c.cn-beijing.personal.cr.aliyuncs.com' + ACR_NAMESPACE = 'xuqmgroup' + ACR_USERNAME = 'xuqinmin12' + PROD_HOST = '106.54.23.149' + PROD_USER = 'ubuntu' + COMPOSE_FILE = '/opt/xuqm/deploy/compose.production.yaml' DOCKER_BUILDKIT = '1' } + options { + timeout(time: 30, unit: 'MINUTES') + buildDiscarder(logRotator(numToKeepStr: '20')) + disableConcurrentBuilds() + } + stages { stage('Checkout') { steps { - checkout([$class: 'GitSCM', - branches: [[name: "*/${params.BRANCH}"]], - extensions: [], + checkout([ + $class: 'GitSCM', + branches: [[name: 'main']], + extensions: [[$class: 'CleanBeforeCheckout']], userRemoteConfigs: scm.userRemoteConfigs ]) } @@ -53,7 +59,7 @@ pipeline { script { def imageName = "${ACR_REGISTRY}/${ACR_NAMESPACE}/${params.SERVICE}:${params.IMAGE_TAG}" bat """ - ssh -i "%SSH_KEY%" -o StrictHostKeyChecking=no ${PROD_USER}@${PROD_HOST} "docker pull ${imageName} && docker compose -f ${COMPOSE_FILE} up -d --no-deps ${params.SERVICE} && docker image prune -f" + ssh -i "%SSH_KEY%" -o StrictHostKeyChecking=no ${PROD_USER}@${PROD_HOST} "docker pull ${imageName} && docker compose -f ${COMPOSE_FILE} up -d --no-deps --force-recreate ${params.SERVICE} && docker image prune -f" """ } }