Jenkins docker部署springcloud项目 编译+构建+回退 Published on Mar 24, 2026 in 随笔 with 0 comment jenkins: image: jenkins/jenkins:lts-jdk21 container_name: jenkins restart: always user: root ports: - "8088:8088" # 访问端口(避免和 nginx 冲突) - "50000:50000" environment: TZ: Asia/Shanghai LANG: C.UTF-8 LC_ALL: C.UTF-8 JENKINS_OPTS: "--httpPort=8088" volumes: - /docker/jenkins/home:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock # 让 Jenkins 可以用宿主机 docker(很关键) - /usr/bin/docker:/usr/bin/docker - /data/fonts:/usr/share/fonts privileged: true network_mode: "host" 1、先安装Jenkins 2、安装nodejs、ssh、maven 3、连接ssh建议使用 key密钥的形式 使用流水线作业 pipeline { agent any parameters { choice( name: 'RUN_MODE', choices: ['deploy', 'rollback'], description: '运行模式:deploy=发布,rollback=回滚' ) choice( name: 'GIT_BRANCH', choices: ['dev', 'test', 'master', 'zhongyalian', 'chancheng_company_show'], description: '代码分支' ) choice( name: 'ACTION', choices: ['compile', 'build', 'all'], description: '构建动作:compile=仅编译,build=仅构建镜像,all=编译+构建镜像' ) string( name: 'SERVICE_NAME', defaultValue: 'all', description: '服务名称,all 表示全部,也可以填 hh-auth / hh-gateway / hh-system' ) booleanParam( name: 'DO_DEPLOY', defaultValue: true, description: '发布模式下是否执行部署' ) } environment { TARGET_SERVER = '8.xx' SCRIPT_PATH = '/docker' SSH_CREDENTIALS_ID = 'e4e8de2b-7cccc0-aae2-1ceca86c1467' } options { timestamps() disableConcurrentBuilds() buildDiscarder(logRotator(numToKeepStr: '20')) } stages { stage('Show Params') { steps { echo "RUN_MODE = ${params.RUN_MODE}" echo "GIT_BRANCH = ${params.GIT_BRANCH}" echo "ACTION = ${params.ACTION}" echo "SERVICE_NAME= ${params.SERVICE_NAME}" echo "DO_DEPLOY = ${params.DO_DEPLOY}" echo "TARGET_SERVER = ${env.TARGET_SERVER}" echo "SCRIPT_PATH = ${env.SCRIPT_PATH}" } } stage('Remote Deploy Build') { when { expression { return params.RUN_MODE == 'deploy' } } steps { script { def cleanBranch = params.GIT_BRANCH.replaceFirst(/^origin\//, '') echo "实际执行分支: ${cleanBranch}" withCredentials([sshUserPrivateKey( credentialsId: env.SSH_CREDENTIALS_ID, keyFileVariable: 'SSH_KEY', usernameVariable: 'SSH_USER' )]) { sh """ ssh -i "${SSH_KEY}" -o StrictHostKeyChecking=no "${SSH_USER}@${env.TARGET_SERVER}" ' cd ${env.SCRIPT_PATH} && chmod +x build-backend-v2.sh && ./build-backend-v2.sh ${params.ACTION} ${cleanBranch} ${params.SERVICE_NAME} ' """ } } } } stage('Remote Deploy Up') { when { allOf { expression { return params.RUN_MODE == 'deploy' } expression { return params.DO_DEPLOY } } } steps { withCredentials([sshUserPrivateKey( credentialsId: env.SSH_CREDENTIALS_ID, keyFileVariable: 'SSH_KEY', usernameVariable: 'SSH_USER' )]) { sh """ ssh -i "${SSH_KEY}" -o StrictHostKeyChecking=no "${SSH_USER}@${env.TARGET_SERVER}" ' cd ${env.SCRIPT_PATH} && chmod +x deploy-v2.sh && ./deploy-v2.sh ${params.SERVICE_NAME} ' """ } } } stage('Remote Rollback') { when { expression { return params.RUN_MODE == 'rollback' } } steps { script { def cleanBranch = params.GIT_BRANCH.replaceFirst(/^origin\//, '') echo "回滚分支: ${cleanBranch}" withCredentials([sshUserPrivateKey( credentialsId: env.SSH_CREDENTIALS_ID, keyFileVariable: 'SSH_KEY', usernameVariable: 'SSH_USER' )]) { sh """ ssh -i "${SSH_KEY}" -o StrictHostKeyChecking=no "${SSH_USER}@${env.TARGET_SERVER}" ' cd ${env.SCRIPT_PATH} && chmod +x rollback-v2.sh && ./rollback-v2.sh ${cleanBranch} ${params.SERVICE_NAME} ' """ } } } } stage('Show Current Version') { steps { withCredentials([sshUserPrivateKey( credentialsId: env.SSH_CREDENTIALS_ID, keyFileVariable: 'SSH_KEY', usernameVariable: 'SSH_USER' )]) { sh """ ssh -i "${SSH_KEY}" -o StrictHostKeyChecking=no "${SSH_USER}@${env.TARGET_SERVER}" ' if [ -f ${env.SCRIPT_PATH}/release-meta/current_commit ]; then echo "当前版本:" cat ${env.SCRIPT_PATH}/release-meta/current_commit fi if [ -f ${env.SCRIPT_PATH}/release-meta/previous_commit ]; then echo "上一个版本:" cat ${env.SCRIPT_PATH}/release-meta/previous_commit fi if [ -f ${env.SCRIPT_PATH}/release-meta/release_history.log ]; then echo "最近发布历史:" tail -5 ${env.SCRIPT_PATH}/release-meta/release_history.log fi ' """ } } } } post { success { echo '✅ 流水线执行成功' } failure { echo '❌ 流水线执行失败' } always { echo '流水线结束' } } } build-backend-v2.sh: #!/bin/bash set -e # ======= 参数控制 ======= BRANCH="chancheng_company_show" DO_MAVEN=false DO_DOCKER=false TARGET_SERVICE="all" # ======= Git 信息 ======= REPO_URL="git@codeup.aliyun.com:66xxxxxxxc07/backend.git" PROJECT_DIR="/data/git-backend" # ======= 发布记录目录 ======= META_DIR="/docker/release-meta" CURRENT_COMMIT_FILE="${META_DIR}/current_commit" PREVIOUS_COMMIT_FILE="${META_DIR}/previous_commit" HISTORY_FILE="${META_DIR}/release_history.log" mkdir -p "$META_DIR" # 解析参数 for arg in "$@"; do case $arg in build) DO_DOCKER=true ;; compile) DO_MAVEN=true ;; all) DO_MAVEN=true DO_DOCKER=true ;; dev|zhongyalian|master|test|chancheng_company_show) BRANCH="$arg" ;; hh-auth|hh-gateway|hh-finance|hh-job|hh-mall|hh-resource|hh-sign|hh-site|hh-system|hh-trade|hh-im|hh-xxl-job-admin|hh-oauth2-server) TARGET_SERVICE="$arg" ;; *) echo "❌ 未知参数: $arg" echo "用法示例:" echo " ./build-backend-v2.sh all dev" echo " ./build-backend-v2.sh build dev hh-auth" exit 1 ;; esac done # ======= 模块映射 ======= get_module_path() { case "$1" in hh-auth) echo "hh-auth" ;; hh-gateway) echo "hh-gateway" ;; hh-finance) echo "hh-modules/hh-finance" ;; hh-job) echo "hh-modules/hh-job" ;; hh-mall) echo "hh-modules/hh-mall" ;; hh-resource) echo "hh-modules/hh-resource" ;; hh-sign) echo "hh-modules/hh-sign" ;; hh-site) echo "hh-modules/hh-site" ;; hh-system) echo "hh-modules/hh-system" ;; hh-trade) echo "hh-modules/hh-trade" ;; hh-im) echo "hh-modules/hh-im" ;; hh-xxl-job-admin) echo "hh-visual/hh-xxl-job-admin" ;; hh-oauth2-server) echo "hh-modules/hh-oauth2-server" ;; *) echo "" ;; esac } # ======= 全量模块 ======= directories=( "hh-auth" "hh-gateway" "hh-modules/hh-finance" "hh-modules/hh-job" "hh-modules/hh-mall" "hh-modules/hh-resource" "hh-modules/hh-sign" "hh-modules/hh-site" "hh-modules/hh-system" "hh-modules/hh-trade" "hh-modules/hh-im" "hh-visual/hh-xxl-job-admin" "hh-modules/hh-oauth2-server" ) echo "=========================================" echo "分支: $BRANCH" echo "Maven编译: $DO_MAVEN" echo "Docker构建: $DO_DOCKER" echo "目标服务: $TARGET_SERVICE" echo "项目目录: $PROJECT_DIR" echo "=========================================" OLD_COMMIT="" NEW_COMMIT="" # ======= 克隆或更新代码 ======= if [ ! -d "$PROJECT_DIR/.git" ]; then echo "📥 克隆后端仓库(分支:$BRANCH)..." rm -rf "$PROJECT_DIR" git clone -b "$BRANCH" "$REPO_URL" "$PROJECT_DIR" || { echo "❌ clone 失败,请检查网络或权限" exit 1 } cd "$PROJECT_DIR" else cd "$PROJECT_DIR" # 记录发布前旧版本 OLD_COMMIT=$(git rev-parse HEAD 2>/dev/null || echo "") if [ -n "$OLD_COMMIT" ]; then echo "$OLD_COMMIT" > "$PREVIOUS_COMMIT_FILE" echo "📌 记录上一个版本: $OLD_COMMIT" fi echo "🔄 更新后端仓库(切换到分支:$BRANCH)..." git fetch origin git checkout "$BRANCH" git pull origin "$BRANCH" fi NEW_COMMIT=$(git rev-parse HEAD) NEW_SHORT_COMMIT=$(git rev-parse --short HEAD) echo "📌 当前版本: $NEW_COMMIT" # ======= Maven 编译 ======= if [ "$DO_MAVEN" = true ]; then echo "🔧 执行 Maven 编译..." cd "$PROJECT_DIR" mvn clean package -Dmaven.test.skip=true || { echo "❌ Maven 编译失败" exit 1 } echo "✅ Maven 编译成功" fi # ======= 构建 Docker 镜像 ======= if [ "$DO_DOCKER" = true ]; then echo "🐳 构建 Docker 镜像..." if [ "$TARGET_SERVICE" = "all" ]; then for dir in "${directories[@]}"; do MODULE_PATH="$PROJECT_DIR/$dir" IMAGE_NAME="${dir##*/}" if [ ! -f "$MODULE_PATH/Dockerfile" ]; then echo "⚠️ 跳过:$IMAGE_NAME,没有 Dockerfile" continue fi echo "🔨 构建镜像: $IMAGE_NAME" cd "$MODULE_PATH" docker build -t "$IMAGE_NAME" . || { echo "❌ 构建失败: $IMAGE_NAME" exit 1 } done else MODULE_RELATIVE_PATH=$(get_module_path "$TARGET_SERVICE") if [ -z "$MODULE_RELATIVE_PATH" ]; then echo "❌ 未找到服务对应模块: $TARGET_SERVICE" exit 1 fi MODULE_PATH="$PROJECT_DIR/$MODULE_RELATIVE_PATH" if [ ! -f "$MODULE_PATH/Dockerfile" ]; then echo "❌ $TARGET_SERVICE 没有 Dockerfile" exit 1 fi echo "🔨 构建单个镜像: $TARGET_SERVICE" cd "$MODULE_PATH" docker build -t "$TARGET_SERVICE" . || { echo "❌ 构建失败: $TARGET_SERVICE" exit 1 } fi echo "✅ Docker 镜像构建完成" fi # ======= 记录成功发布版本 ======= echo "$NEW_COMMIT" > "$CURRENT_COMMIT_FILE" echo "$(date '+%F %T') | branch=$BRANCH | service=$TARGET_SERVICE | action=$* | commit=$NEW_COMMIT | short=$NEW_SHORT_COMMIT" >> "$HISTORY_FILE" echo "✅ 已记录当前成功版本: $NEW_COMMIT" deploy-v2.sh: #!/bin/bash set -e SERVICE_NAME="${1:-all}" COMPOSE_FILE="/docker/docker-compose.yml" BUSINESS_SERVICES=( hh-xxl-job-admin hh-gateway hh-auth hh-system hh-job hh-resource hh-finance hh-mall hh-sign hh-site hh-trade hh-im hh-oauth2-server ) echo "=========================================" echo "部署目标: $SERVICE_NAME" echo "Compose文件: $COMPOSE_FILE" echo "=========================================" if [ ! -f "$COMPOSE_FILE" ]; then echo "❌ docker-compose 文件不存在: $COMPOSE_FILE" exit 1 fi cd /docker if docker compose version >/dev/null 2>&1; then COMPOSE_CMD="docker compose" elif command -v docker-compose >/dev/null 2>&1; then COMPOSE_CMD="docker-compose" else echo "❌ 未找到 docker compose / docker-compose" exit 1 fi if [ "$SERVICE_NAME" = "all" ]; then echo "🚀 发布全部业务服务..." $COMPOSE_CMD -f "$COMPOSE_FILE" up -d "${BUSINESS_SERVICES[@]}" else echo "🚀 发布单个服务: $SERVICE_NAME" $COMPOSE_CMD -f "$COMPOSE_FILE" up -d "$SERVICE_NAME" fi echo "📋 当前服务状态:" $COMPOSE_CMD -f "$COMPOSE_FILE" ps echo "✅ 部署完成" rollback-v2.sh #!/bin/bash set -e BRANCH="${1:-chancheng_company_show}" SERVICE_NAME="${2:-all}" PROJECT_DIR="/data/git-backend" COMPOSE_FILE="/docker/docker-compose.yml" META_DIR="/data/scripts/release-meta" CURRENT_COMMIT_FILE="${META_DIR}/current_commit" PREVIOUS_COMMIT_FILE="${META_DIR}/previous_commit" HISTORY_FILE="${META_DIR}/release_history.log" # ======= 模块映射 ======= get_module_path() { case "$1" in hh-auth) echo "hh-auth" ;; hh-gateway) echo "hh-gateway" ;; hh-finance) echo "hh-modules/hh-finance" ;; hh-job) echo "hh-modules/hh-job" ;; hh-mall) echo "hh-modules/hh-mall" ;; hh-resource) echo "hh-modules/hh-resource" ;; hh-sign) echo "hh-modules/hh-sign" ;; hh-site) echo "hh-modules/hh-site" ;; hh-system) echo "hh-modules/hh-system" ;; hh-trade) echo "hh-modules/hh-trade" ;; hh-im) echo "hh-modules/hh-im" ;; hh-xxl-job-admin) echo "hh-visual/hh-xxl-job-admin" ;; hh-oauth2-server) echo "hh-modules/hh-oauth2-server" ;; *) echo "" ;; esac } directories=( "hh-auth" "hh-gateway" "hh-modules/hh-finance" "hh-modules/hh-job" "hh-modules/hh-mall" "hh-modules/hh-resource" "hh-modules/hh-sign" "hh-modules/hh-site" "hh-modules/hh-system" "hh-modules/hh-trade" "hh-modules/hh-im" "hh-visual/hh-xxl-job-admin" "hh-modules/hh-oauth2-server" ) BUSINESS_SERVICES=( hh-xxl-job-admin hh-gateway hh-auth hh-system hh-job hh-resource hh-finance hh-mall hh-sign hh-site hh-trade hh-im hh-oauth2-server ) if [ ! -f "$PREVIOUS_COMMIT_FILE" ]; then echo "❌ 没有找到 previous_commit,无法回滚" exit 1 fi ROLLBACK_COMMIT=$(cat "$PREVIOUS_COMMIT_FILE") echo "=========================================" echo "回滚分支: $BRANCH" echo "回滚服务: $SERVICE_NAME" echo "回滚版本: $ROLLBACK_COMMIT" echo "=========================================" cd "$PROJECT_DIR" git fetch origin git checkout "$BRANCH" git reset --hard "$ROLLBACK_COMMIT" echo "🔧 Maven 重新编译..." mvn clean package -Dmaven.test.skip=true echo "🐳 重新构建镜像..." if [ "$SERVICE_NAME" = "all" ]; then for dir in "${directories[@]}"; do MODULE_PATH="$PROJECT_DIR/$dir" IMAGE_NAME="${dir##*/}" if [ ! -f "$MODULE_PATH/Dockerfile" ]; then echo "⚠️ 跳过:$IMAGE_NAME,没有 Dockerfile" continue fi echo "🔨 回滚构建镜像: $IMAGE_NAME" cd "$MODULE_PATH" docker build -t "$IMAGE_NAME" . done else MODULE_RELATIVE_PATH=$(get_module_path "$SERVICE_NAME") if [ -z "$MODULE_RELATIVE_PATH" ]; then echo "❌ 未找到服务对应模块: $SERVICE_NAME" exit 1 fi MODULE_PATH="$PROJECT_DIR/$MODULE_RELATIVE_PATH" cd "$MODULE_PATH" docker build -t "$SERVICE_NAME" . fi if docker compose version >/dev/null 2>&1; then COMPOSE_CMD="docker compose" elif command -v docker-compose >/dev/null 2>&1; then COMPOSE_CMD="docker-compose" else echo "❌ 未找到 docker compose / docker-compose" exit 1 fi echo "🚀 发布回滚版本..." if [ "$SERVICE_NAME" = "all" ]; then $COMPOSE_CMD -f "$COMPOSE_FILE" up -d "${BUSINESS_SERVICES[@]}" else $COMPOSE_CMD -f "$COMPOSE_FILE" up -d "$SERVICE_NAME" fi # 回滚后更新 current_commit echo "$ROLLBACK_COMMIT" > "$CURRENT_COMMIT_FILE" echo "$(date '+%F %T') | rollback | branch=$BRANCH | service=$SERVICE_NAME | commit=$ROLLBACK_COMMIT" >> "$HISTORY_FILE" echo "✅ 回滚完成" 本文由 admin 创作,采用 知识共享署名4.0 国际许可协议进行许可。本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。