pipeline { // 在任意可用节点执行(你是单机就只有 master/内置节点) agent any options { // 单机一定要禁并发:避免同时构建/部署互相覆盖容器 disableConcurrentBuilds() // 控制台输出带时间戳,排查问题更方便 timestamps() } environment { // 运行容器的名字:固定一个,方便停旧启新 APP_NAME = "agri" // 容器内程序监听端口 & 宿主机映射端口(这里同端口) PORT = "8088" // 部署目录:你已经把宿主机 /opt/agri 挂载进 Jenkins 容器了 // 这里常用来放日志、当前版本号等 DEPLOY_DIR = "/opt/agri" // 镜像仓库名(本机镜像名即可) // 最终镜像:agri-backend:${BUILD_NUMBER} IMAGE_REPO = "agri-backend" // 记录“当前部署的构建号”,方便你手动回滚时知道上一版是啥 CURRENT_TAG_FILE = "/opt/agri/current_tag" // 多模块项目的“真正启动模块” // 你这个结构里一般就是 agri-admin BOOT_MODULE = "agri-admin" } stages { stage('Checkout') { steps { // 从 Jenkins Job 配置的 SCM 拉代码(ssh gitea) checkout scm } } stage('Build Jar (JDK8, multi-module)') { // 用 Maven+JDK8 的构建容器来编译,避免你在服务器/jenkins里安装 JDK8/Maven // 注意:这个 stage 运行在一个临时容器里,但 workspace 是共享的 agent { docker { // Maven 3.9 + Temurin JDK8 image 'maven:3.9.6-eclipse-temurin-8' // 挂载 Maven 本地仓库缓存,加速第二次构建 // $HOME 指 Jenkins 容器内的 home,通常在 /var/jenkins_home args '-v $HOME/.m2:/root/.m2' } } steps { sh ''' set -e echo "==== Build multi-module boot module: ${BOOT_MODULE} ====" # -pl ${BOOT_MODULE}:只构建启动模块 # -am:同时构建它依赖的其它模块(common/framework/system等) # -DskipTests:跳过测试,加速 mvn -B -DskipTests -pl ${BOOT_MODULE} -am clean package echo "==== Pick jar from ${BOOT_MODULE}/target ====" ls -lh ${BOOT_MODULE}/target || true # 创建根目录 target(与 Dockerfile 对齐:COPY target/agri.jar) mkdir -p target # 找一个可运行 jar:排除 sources/javadoc(如果有 original 也可以再排除) jar=$(ls -1 ${BOOT_MODULE}/target/*.jar | grep -v 'sources\\|javadoc' | head -n 1) echo "Selected jar: $jar" # 统一命名为 target/agri.jar,后续 docker build 直接 COPY cp -f "$jar" target/agri.jar echo "==== Final artifact ====" ls -lh target/agri.jar ''' } } stage('Build Image') { steps { sh ''' set -e # 构建镜像:agri-backend:${BUILD_NUMBER} # Dockerfile 会 COPY target/agri.jar docker build -t ${IMAGE_REPO}:${BUILD_NUMBER} . echo "Built image: ${IMAGE_REPO}:${BUILD_NUMBER}" ''' } } stage('Deploy') { steps { sh ''' set -e echo "==== Deploy to ${DEPLOY_DIR} ====" mkdir -p "${DEPLOY_DIR}" # 1) 停旧容器(不存在也没关系) docker rm -f ${APP_NAME} >/dev/null 2>&1 || true # 2) 启新容器 # --restart unless-stopped:机器重启后自动起来 # -p 8088:8088:把宿主机 8088 映射到容器 8088 # -v /opt/agri/logs:/app/logs:把日志落到宿主机 /opt/agri/logs docker run -d \ --name ${APP_NAME} \ --restart unless-stopped \ -p ${PORT}:${PORT} \ -v ${DEPLOY_DIR}/logs:/app/logs \ ${IMAGE_REPO}:${BUILD_NUMBER} # 记录当前版本号(手动回滚时用) echo "${BUILD_NUMBER}" > "${CURRENT_TAG_FILE}" echo "Deployed: ${IMAGE_REPO}:${BUILD_NUMBER}" echo "Current tag file: ${CURRENT_TAG_FILE} -> $(cat ${CURRENT_TAG_FILE})" ''' } } } post { always { // 每次构建结束都打印一下当前容器状态,排查更方便 sh ''' echo "==== docker ps (agri) ====" docker ps --filter "name=^/agri$" || true ''' } } }