cdpipeline { agent any tools { jdk 'jdk21' } parameters { string( name: 'DEPLOY_SERVERS', defaultValue: '192.168.0.212', description: '部署的目标服务器,多个目标服务器以英文逗号分隔,如:192.168.0.212,192.168.0.47,192.168.0.79' ) choice( name: 'spring.profiles.active', choices: ['dev','test', 'prod'], description: '选择要激活的 Spring Profile' ) } environment { BASE_IMAGE_NAME = 'seer-admin' SSH_CREDENTIALS_ID = 'seerTeachPubKey' DEPLOY_USER = 'root' LOGS_HOST_PATH = '/app/java/seer-admin/logs' LOGS_CONTAINER_PATH = '/app/java/seer-admin/logs' } options { timeout(time: 30, unit: 'MINUTES') skipDefaultCheckout(true) } stages { stage('初始化 & 分支校验') { steps { script { sh 'echo "初始Git工作目录: $(pwd)"' sh 'ls -la ' def scmVars = checkout scm env.GIT_COMMIT = scmVars.GIT_COMMIT env.GIT_BRANCH = scmVars.GIT_BRANCH // 清理分支名称,替换非法字符,确保符合 Docker 标签命名规范 env.BRANCH_CLEAN = env.GIT_BRANCH.replaceAll(/[^\w.-]/, '-') env.IMAGE_TAG = "${BASE_IMAGE_NAME}:${env.BRANCH_CLEAN}" env.TAR_FILE = "${BASE_IMAGE_NAME}_${env.BRANCH_CLEAN}.tar" echo " 初始化完成" echo "原始分支:${env.GIT_BRANCH}" echo "清理后分支:${env.BRANCH_CLEAN}" echo "镜像标签:${env.IMAGE_TAG}" echo "目标服务器:${params.DEPLOY_SERVERS}" } } } stage('构建 Maven 项目') { steps { script { sh ''' JAVA_HOME=/opt/java/openjdk \ PATH=/opt/java/openjdk/bin:$PATH \ mvn clean package -Dmaven.test.skip=true -pl :seer-admin -am ''' echo " Maven 构建完成" } } } stage('构建 Docker 镜像') { steps { dir('seer-admin') { sh "docker build -t ${env.IMAGE_TAG} ." echo " Docker 镜像构建成功:${env.IMAGE_TAG}" } } } stage('导出并传输镜像') { steps { script { sh 'echo "导出并传输镜像工作目录: $(pwd)"' sh "docker save -o ${env.TAR_FILE} ${env.IMAGE_TAG}" echo "镜像已导出为文件:${env.TAR_FILE}" def servers = params.DEPLOY_SERVERS.split(',') servers.each { server -> sshagent([env.SSH_CREDENTIALS_ID]) { def sev = server.trim() sh "scp -o StrictHostKeyChecking=no ${env.TAR_FILE} ${DEPLOY_USER}@${sev}:/tmp/" } echo " 镜像已传输到远程服务器:${server}" } } } } stage('远程部署镜像') { steps { script { def servers = params.DEPLOY_SERVERS.split(',') servers.each { server -> deployToServer(server.trim()) } } } } } post { always { script { if (env.TAR_FILE?.trim()) { sh "rm -f ${env.TAR_FILE} || true" } deleteDir() } } success { echo " 构建成功:分支 ${env.GIT_BRANCH},镜像 ${env.IMAGE_TAG}" } failure { echo " 构建失败:分支 ${env.GIT_BRANCH}" } } } def deployToServer(server){ sshagent([env.SSH_CREDENTIALS_ID]) { sh """ ssh -o StrictHostKeyChecking=no ${DEPLOY_USER}@${server} << 'EOF' set -e echo "🛠 加载镜像..." docker load -i /tmp/${env.TAR_FILE} echo " 停止并移除旧容器(如果存在)..." docker stop ${BASE_IMAGE_NAME} || true docker rm ${BASE_IMAGE_NAME} || true echo " 创建日志目录..." mkdir -p ${LOGS_HOST_PATH} echo " 启动新容器..." echo "激活的 Profile: ${params['spring.profiles.active']}" docker run -d --name ${BASE_IMAGE_NAME} -p 6060:6060 \\ -v ${LOGS_HOST_PATH}:${LOGS_CONTAINER_PATH} \\ -e NACOS_DISCOVERY_IP=${server} \\ -e SPRING_PROFILES_ACTIVE=${params['spring.profiles.active']} \\ --restart=always \\ ${env.IMAGE_TAG} EOF """ echo " 镜像已部署到远程服务器:${server}" } }