CI/CD 实战:用 Jenkins 自动构建和部署你的项目

1. 引言

在当今快速迭代的软件开发环境中,持续集成和持续部署(CI/CD)已成为现代 DevOps 实践的核心组成部分。Jenkins 作为最流行的开源自动化服务器,提供了强大的 CI/CD 功能,能够帮助团队自动化构建、测试和部署流程。

本教程将手把手教你搭建完整的 Jenkins CI/CD 流水线,从环境配置到自动化部署,每个步骤都包含详细的代码和配置说明。

2. 环境准备与 Jenkins 安装

2.1 系统要求

  • Ubuntu 20.04 LTS 或 CentOS 8
  • 至少 4GB RAM
  • 20GB 可用磁盘空间
  • Java 11 或更高版本

2.2 安装 Java

创建安装脚本文件: install_java.sh

bash 复制代码
#!/bin/bash

# 更新系统包管理器
sudo apt update && sudo apt upgrade -y

# 安装 Java 11
sudo apt install -y openjdk-11-jdk

# 验证安装
java -version
javac -version

# 设置 JAVA_HOME 环境变量
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64' >> ~/.bashrc
echo 'export PATH=$JAVA_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

运行脚本:

bash 复制代码
chmod +x install_java.sh
./install_java.sh

2.3 安装 Jenkins

创建 Jenkins 安装脚本: install_jenkins.sh

bash 复制代码
#!/bin/bash

# 下载并添加 Jenkins 仓库密钥
curl -fsSL https://pkg.jenkins.io/debian/jenkins.io.key | sudo tee \
  /usr/share/keyrings/jenkins-keyring.asc > /dev/null

# 添加 Jenkins 仓库
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list > /dev/null

# 更新包列表并安装 Jenkins
sudo apt update
sudo apt install -y jenkins

# 启动 Jenkins 服务
sudo systemctl enable jenkins
sudo systemctl start jenkins
sudo systemctl status jenkins

# 开放 Jenkins 默认端口 8080
sudo ufw allow 8080
sudo ufw status

运行安装脚本:

bash 复制代码
chmod +x install_jenkins.sh
./install_jenkins.sh

2.4 初始 Jenkins 配置

访问 http://your-server-ip:8080 完成初始设置:

bash 复制代码
# 获取初始管理员密码
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

按照向导安装推荐插件并创建管理员账户。

3. Jenkins 系统配置

3.1 安装必要插件

创建插件安装脚本: install_plugins.sh

bash 复制代码
#!/bin/bash

# Jenkins CLI 安装插件
JENKINS_URL="http://localhost:8080"
JENKINS_CLI_JAR="/var/lib/jenkins/jenkins-cli.jar"

# 插件列表
PLUGINS=(
    "git"
    "github"
    "pipeline"
    "docker"
    "blueocean"
    "credentials-binding"
    "ssh-agent"
    "email-ext"
    "htmlpublisher"
    "jacoco"
    "sonar"
    "slack"
)

# 安装每个插件
for plugin in "${PLUGINS[@]}"; do
    echo "安装插件: $plugin"
    java -jar $JENKINS_CLI_JAR -s $JENKINS_URL install-plugin $plugin -deploy
done

# 重启 Jenkins 使插件生效
sudo systemctl restart jenkins

3.2 配置系统环境

在 Jenkins 管理界面中配置:

  1. 全局工具配置

    • JDK:配置 Java 11 路径
    • Git:配置 Git 可执行文件路径
    • Maven/Gradle:根据需要配置构建工具
  2. 凭据配置

    • 添加 GitHub SSH 密钥
    • 添加 Docker Hub 凭据
    • 添加服务器 SSH 凭据

4. 示例项目准备

4.1 创建 Spring Boot 示例应用

创建项目结构:

css 复制代码
sample-spring-app/
├── src/
│   └── main/
│       └── java/
│           └── com/
│               └── example/
│                   └── demo/
│                       └── DemoApplication.java
├── pom.xml
├── Dockerfile
├── Jenkinsfile
└── k8s/
    └── deployment.yaml

创建 Maven 配置文件: pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.example</groupId>
    <artifactId>sample-spring-app</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <name>Sample Spring Boot Application</name>
    <description>Demo project for Jenkins CI/CD</description>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath/>
    </parent>
    
    <properties>
        <java.version>11</java.version>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.8</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>report</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

创建 Spring Boot 主类: src/main/java/com/example/demo/DemoApplication.java

java 复制代码
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @GetMapping("/")
    public String home() {
        return "Hello from Spring Boot CI/CD Demo!";
    }

    @GetMapping("/health")
    public String health() {
        return "Application is healthy!";
    }
}

4.2 创建 Docker 配置

创建 Dockerfile: Dockerfile

dockerfile 复制代码
# 使用 OpenJDK 11 作为基础镜像
FROM openjdk:11-jre-slim

# 设置工作目录
WORKDIR /app

# 添加 JAR 文件到容器
COPY target/sample-spring-app-1.0.0.jar app.jar

# 创建非 root 用户
RUN groupadd -r spring && useradd -r -g spring spring
USER spring

# 暴露端口
EXPOSE 8080

# 设置 JVM 参数
ENV JAVA_OPTS="-Xms256m -Xmx512m -Djava.security.egd=file:/dev/./urandom"

# 启动应用
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

创建 Docker Compose 文件: docker-compose.yml

yaml 复制代码
version: '3.8'

services:
  spring-app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - spring-app
    restart: unless-stopped

5. Jenkins Pipeline 配置

5.1 创建 Jenkinsfile

创建 Jenkinsfile: Jenkinsfile

groovy 复制代码
pipeline {
    agent any
    
    environment {
        // 应用配置
        APP_NAME = 'sample-spring-app'
        APP_VERSION = '1.0.0'
        
        // 容器注册表配置
        DOCKER_REGISTRY = 'docker.io'
        DOCKER_CREDENTIALS = 'docker-hub-credentials'
        
        // 服务器配置
        DEPLOY_SERVER = 'deploy-server'
        DEPLOY_PATH = '/opt/apps'
        
        // SonarQube 配置
        SONAR_HOST_URL = 'http://sonarqube:9000'
        SONAR_CREDENTIALS = 'sonar-token'
    }
    
    options {
        timeout(time: 30, unit: 'MINUTES')
        buildDiscarder(logRotator(numToKeepStr: '10'))
        disableConcurrentBuilds()
    }
    
    parameters {
        choice(
            name: 'DEPLOY_ENV',
            choices: ['dev', 'staging', 'prod'],
            description: '选择部署环境'
        )
        booleanParam(
            name: 'RUN_INTEGRATION_TESTS',
            defaultValue: true,
            description: '是否运行集成测试'
        )
    }
    
    stages {
        stage('代码检出') {
            steps {
                checkout scm
                script {
                    currentBuild.displayName = "#${BUILD_NUMBER}-${params.DEPLOY_ENV}"
                    currentBuild.description = "分支: ${env.BRANCH_NAME}"
                }
            }
        }
        
        stage('代码质量检查') {
            steps {
                withSonarQubeEnv('sonarqube') {
                    sh 'mvn clean verify sonar:sonar -Dsonar.projectKey=sample-spring-app'
                }
            }
        }
        
        stage('编译构建') {
            steps {
                sh """
                    mvn clean compile -DskipTests
                    echo "编译完成"
                """
            }
        }
        
        stage('单元测试') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'
                    jacoco(
                        execPattern: 'target/jacoco.exec',
                        classPattern: 'target/classes',
                        sourcePattern: 'src/main/java'
                    )
                }
            }
        }
        
        stage('集成测试') {
            when {
                expression { params.RUN_INTEGRATION_TESTS }
            }
            steps {
                sh 'mvn verify -Pintegration-tests'
            }
            post {
                always {
                    junit 'target/failsafe-reports/*.xml'
                }
            }
        }
        
        stage('代码质量门禁') {
            steps {
                timeout(time: 5, unit: 'MINUTES') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }
        
        stage('构建 Docker 镜像') {
            steps {
                script {
                    docker.build("${DOCKER_REGISTRY}/${APP_NAME}:${APP_VERSION}-${env.BUILD_NUMBER}")
                }
            }
        }
        
        stage('安全扫描') {
            steps {
                sh """
                    docker scan --file Dockerfile ${DOCKER_REGISTRY}/${APP_NAME}:${APP_VERSION}-${env.BUILD_NUMBER}
                """
            }
        }
        
        stage('推送镜像') {
            steps {
                script {
                    docker.withRegistry("https://${DOCKER_REGISTRY}", DOCKER_CREDENTIALS) {
                        docker.image("${DOCKER_REGISTRY}/${APP_NAME}:${APP_VERSION}-${env.BUILD_NUMBER}").push()
                    }
                }
            }
        }
        
        stage('部署到环境') {
            when {
                expression { params.DEPLOY_ENV != 'none' }
            }
            steps {
                script {
                    deployToEnvironment(params.DEPLOY_ENV)
                }
            }
        }
    }
    
    post {
        always {
            emailext (
                subject: "构建通知: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
                body: """
                    <h2>构建信息</h2>
                    <p><b>项目:</b> ${env.JOB_NAME}</p>
                    <p><b>构建号:</b> ${env.BUILD_NUMBER}</p>
                    <p><b>状态:</b> ${currentBuild.result ?: 'SUCCESS'}</p>
                    <p><b>持续时间:</b> ${currentBuild.durationString}</p>
                    <p><b>部署环境:</b> ${params.DEPLOY_ENV}</p>
                    <p><a href="${env.BUILD_URL}">查看构建详情</a></p>
                """,
                to: "dev-team@company.com",
                attachLog: currentBuild.result != 'SUCCESS'
            )
            
            cleanWs()
        }
        success {
            slackSend(
                channel: '#build-notifications',
                message: "✅ 构建成功: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                color: 'good'
            )
        }
        failure {
            slackSend(
                channel: '#build-notifications',
                message: "❌ 构建失败: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                color: 'danger'
            )
        }
        unstable {
            slackSend(
                channel: '#build-notifications',
                message: "⚠️ 构建不稳定: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                color: 'warning'
            )
        }
    }
}

// 部署到不同环境的方法
def deployToEnvironment(env) {
    switch(env) {
        case 'dev':
            deployDev()
            break
        case 'staging':
            deployStaging()
            break
        case 'prod':
            deployProd()
            break
        default:
            error "未知环境: ${env}"
    }
}

def deployDev() {
    sshagent([DEPLOY_SERVER]) {
        sh """
            ssh -o StrictHostKeyChecking=no deploy@dev-server "
                cd ${DEPLOY_PATH} &&
                docker-compose pull &&
                docker-compose up -d &&
                sleep 10 &&
                echo '开发环境部署完成'
            "
        """
    }
}

def deployStaging() {
    sshagent([DEPLOY_SERVER]) {
        sh """
            ssh -o StrictHostKeyChecking=no deploy@staging-server "
                cd ${DEPLOY_PATH} &&
                docker-compose pull &&
                docker-compose up -d &&
                sleep 10 &&
                echo '预发布环境部署完成'
            "
        """
    }
}

def deployProd() {
    sshagent([DEPLOY_SERVER]) {
        sh """
            ssh -o StrictHostKeyChecking=no deploy@prod-server "
                cd ${DEPLOY_PATH} &&
                docker-compose pull &&
                docker-compose up -d &&
                sleep 10 &&
                echo '生产环境部署完成'
            "
        """
    }
}

5.2 CI/CD 流程可视化

以下是完整的 CI/CD 流程示意图:

flowchart TD A[📥 代码提交] --> B[🛡️ 代码质量检查] B --> C[🔨 编译构建] C --> D[🧪 单元测试] D --> E[⚙️ 集成测试] E --> F[📊 质量门禁] F --> G[🐳 构建Docker镜像] G --> H[🔒 安全扫描] H --> I[📦 推送镜像] I --> J{选择部署环境} J --> K[🌱 开发环境] J --> L[🔄 预发布环境] J --> M[🚀 生产环境] K --> N[📊 部署完成] L --> N M --> N N --> O[📧 邮件通知] N --> P[💬 Slack通知] style A fill:#4CAF50,color:white style B fill:#2196F3,color:white style C fill:#2196F3,color:white style D fill:#FF9800,color:white style E fill:#FF9800,color:white style F fill:#9C27B0,color:white style G fill:#607D8B,color:white style H fill:#F44336,color:white style I fill:#4CAF50,color:white style J fill:#FFC107,color:black style K fill:#8BC34A,color:white style L fill:#FF9800,color:white style M fill:#F44336,color:white style N fill:#4CAF50,color:white style O fill:#2196F3,color:white style P fill:#4CAF50,color:white

6. 高级配置与优化

6.1 创建共享库

创建共享库结构:

css 复制代码
jenkins-shared-library/
├── vars/
│   └── deployUtils.groovy
├── src/
│   └── com/
│       └── company/
│           └── BuildUtils.groovy
└── resources/
    └── com/
        └── company/
            └── templates/
                └── deployment.yaml

创建共享工具类: vars/deployUtils.groovy

groovy 复制代码
#!/usr/bin/groovy

def call(Map config = [:]) {
    def defaults = [
        timeout: 30,
        retries: 3,
        healthCheckUrl: '',
        rollbackOnFailure: true
    ]
    config = defaults + config
    
    pipeline {
        agent any
        
        stages {
            stage('预部署检查') {
                steps {
                    script {
                        checkPrerequisites()
                        validateConfig(config)
                    }
                }
            }
            
            stage('部署') {
                steps {
                    retry(config.retries) {
                        timeout(time: config.timeout, unit: 'MINUTES') {
                            script {
                                performDeployment(config)
                            }
                        }
                    }
                }
            }
            
            stage('健康检查') {
                steps {
                    script {
                        healthCheck(config.healthCheckUrl)
                    }
                }
            }
        }
        
        post {
            failure {
                script {
                    if (config.rollbackOnFailure) {
                        rollbackDeployment()
                    }
                    notifyFailure()
                }
            }
            success {
                notifySuccess()
            }
        }
    }
}

def checkPrerequisites() {
    // 检查部署前提条件
    sh 'echo "检查部署前提条件..."'
}

def validateConfig(config) {
    // 验证配置
    if (!config.healthCheckUrl) {
        error "健康检查URL不能为空"
    }
}

def performDeployment(config) {
    // 执行部署逻辑
    sh 'echo "执行部署..."'
}

def healthCheck(url) {
    // 健康检查
    sh """
        echo "执行健康检查: ${url}"
        curl -f ${url} || exit 1
    """
}

def rollbackDeployment() {
    // 回滚部署
    sh 'echo "执行回滚..."'
}

def notifyFailure() {
    // 失败通知
    emailext(
        subject: "部署失败: ${env.JOB_NAME}",
        body: "部署失败,请检查日志。",
        to: "devops@company.com"
    )
}

def notifySuccess() {
    // 成功通知
    emailext(
        subject: "部署成功: ${env.JOB_NAME}",
        body: "部署成功完成。",
        to: "devops@company.com"
    )
}

6.2 配置 Jenkins 凭据

创建凭据配置脚本: configure_credentials.sh

bash 复制代码
#!/bin/bash

# 配置 Docker Hub 凭据
java -jar /var/lib/jenkins/jenkins-cli.jar -s http://localhost:8080 groovy = <<EOF
import com.cloudbees.plugins.credentials.*
import com.cloudbees.plugins.credentials.domains.*
import com.cloudbees.plugins.credentials.impl.*
import com.cloudbees.jenkins.plugins.sshcredentials.impl.*
import org.jenkinsci.plugins.plaincredentials.impl.*
import hudson.util.Secret

domain = Domain.global()
store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()

// Docker Hub 用户名密码凭据
dockerHubCredentials = new UsernamePasswordCredentialsImpl(
    CredentialsScope.GLOBAL,
    "docker-hub-credentials",
    "Docker Hub Credentials",
    "your-docker-username",
    "your-docker-password"
)

// SSH 部署密钥
sshCredentials = new BasicSSHUserPrivateKey(
    CredentialsScope.GLOBAL,
    "deploy-ssh-key",
    "deploy-user",
    new BasicSSHUserPrivateKey.UsersPrivateKeySource(),
    "",
    "Deployment SSH Key"
)

// 添加凭据到存储
store.addCredentials(domain, dockerHubCredentials)
store.addCredentials(domain, sshCredentials)

println "凭据配置完成"
EOF

7. 监控与日志

7.1 配置构建监控

创建监控仪表板配置: configure_monitoring.sh

bash 复制代码
#!/bin/bash

# 安装监控插件
java -jar /var/lib/jenkins/jenkins-cli.jar -s http://localhost:8080 install-plugin monitoring -deploy
java -jar /var/lib/jenkins/jenkins-cli.jar -s http://localhost:8080 install-plugin build-monitor-plugin -deploy

# 重启 Jenkins
sudo systemctl restart jenkins

# 配置构建历史清理
cat > /var/lib/jenkins/job-config-history.xml << EOF
<org.jenkinsci.plugins.jobConfigHistory.JobConfigHistory>
  <maxHistory>30</maxHistory>
  <saveModuleConfiguration>true</saveModuleConfiguration>
  <skipDuplicateHistory>true</skipDuplicateHistory>
</org.jenkinsci.plugins.jobConfigHistory.JobConfigHistory>
EOF

7.2 日志配置

创建日志配置: logging_config.groovy

groovy 复制代码
import java.util.logging.ConsoleHandler
import java.util.logging.FileHandler
import java.util.logging.SimpleFormatter

// 配置 Jenkins 日志
def logger = java.util.logging.Logger.getLogger("")

// 清除现有处理器
logger.handlers.each { logger.removeHandler(it) }

// 控制台处理器
def consoleHandler = new ConsoleHandler()
consoleHandler.level = java.util.logging.Level.INFO
logger.addHandler(consoleHandler)

// 文件处理器
def fileHandler = new FileHandler("/var/log/jenkins/jenkins.log", 10485760, 10, true)
fileHandler.level = java.util.logging.Level.ALL
fileHandler.formatter = new SimpleFormatter()
logger.addHandler(fileHandler)

// 设置日志级别
logger.level = java.util.logging.Level.ALL

8. 安全配置

8.1 Jenkins 安全加固

创建安全配置脚本: security_hardening.sh

bash 复制代码
#!/bin/bash

# 备份原始配置
cp /var/lib/jenkins/config.xml /var/lib/jenkins/config.xml.backup

# 配置安全性设置
cat > /var/lib/jenkins/security.groovy << EOF
import jenkins.model.*
import hudson.security.*
import jenkins.security.s2m.AdminWhitelistRule

def instance = Jenkins.getInstance()

// 启用安全性
def strategy = new GlobalMatrixAuthorizationStrategy()

// 添加权限
strategy.add(Jenkins.ADMINISTER, "admin")
strategy.add(Jenkins.READ, "authenticated")
strategy.add(hudson.model.Item.READ, "authenticated")
strategy.add(hudson.model.Item.BUILD, "authenticated")
strategy.add(hudson.model.Item.CONFIGURE, "admin")

instance.setAuthorizationStrategy(strategy)

// 配置安全领域
def realm = new HudsonPrivateSecurityRealm(false)
realm.createAccount("admin", "secure-password-here")
instance.setSecurityRealm(realm)

// 禁用 Jenkins CLI 远程访问
instance.getDescriptor("jenkins.CLI").get().setEnabled(false)

// 保存配置
instance.save()
EOF

# 执行安全配置
java -jar /var/lib/jenkins/jenkins-cli.jar -s http://localhost:8080 groovy security.groovy

# 清理
rm /var/lib/jenkins/security.groovy

echo "Jenkins 安全配置完成"

9. 故障排除与维护

9.1 常见问题解决

创建故障排除脚本: troubleshooting.sh

bash 复制代码
#!/bin/bash

echo "=== Jenkins 故障排除工具 ==="

# 检查服务状态
echo "1. 检查 Jenkins 服务状态..."
sudo systemctl status jenkins --no-pager -l

# 检查磁盘空间
echo "2. 检查磁盘空间..."
df -h /var/lib/jenkins

# 检查内存使用
echo "3. 检查内存使用..."
free -h

# 检查日志错误
echo "4. 检查最近错误..."
tail -100 /var/log/jenkins/jenkins.log | grep -i error

# 检查构建队列
echo "5. 检查构建队列..."
java -jar /var/lib/jenkins/jenkins-cli.jar -s http://localhost:8080 list-queue

# 检查插件更新
echo "6. 检查可用插件更新..."
java -jar /var/lib/jenkins/jenkins-cli.jar -s http://localhost:8080 list-plugins | grep -i available

echo "故障排除检查完成"

9.2 备份与恢复

创建备份脚本: backup_jenkins.sh

bash 复制代码
#!/bin/bash

BACKUP_DIR="/opt/jenkins-backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="jenkins_backup_${TIMESTAMP}.tar.gz"

echo "开始备份 Jenkins..."

# 创建备份目录
mkdir -p $BACKUP_DIR

# 停止 Jenkins 服务
sudo systemctl stop jenkins

# 创建备份
sudo tar -czf $BACKUP_DIR/$BACKUP_FILE \
    --exclude='./war' \
    --exclude='./cache' \
    --exclude='./logs' \
    -C /var/lib jenkins

# 启动 Jenkins 服务
sudo systemctl start jenkins

# 验证备份
if [ -f "$BACKUP_DIR/$BACKUP_FILE" ]; then
    echo "备份成功: $BACKUP_DIR/$BACKUP_FILE"
    echo "备份大小: $(du -h $BACKUP_DIR/$BACKUP_FILE | cut -f1)"
else
    echo "备份失败!"
    exit 1
fi

# 清理旧备份(保留最近7天)
find $BACKUP_DIR -name "jenkins_backup_*.tar.gz" -mtime +7 -delete

echo "备份完成"

10. 总结

通过本教程,你已经学会了如何:

  1. 安装和配置 Jenkins 服务器
  2. 创建完整的 CI/CD 流水线 使用 Jenkins Pipeline
  3. 集成代码质量检查 和自动化测试
  4. 构建和部署 Docker 容器
  5. 配置多环境部署 策略
  6. 实现监控和通知 机制
  7. 加强 Jenkins 安全性
  8. 设置备份和恢复 流程

这个完整的 Jenkins CI/CD 解决方案可以帮助团队实现高效的自动化构建和部署流程,提高软件交付质量和速度。记得根据你的具体需求调整配置,并定期更新和维护你的 Jenkins 环境。

相关推荐
阿干tkl2 小时前
Linux 虚拟机模板制作指南
linux·vmware
裤裤兔3 小时前
linux提取指定前缀文件到其他文件夹
linux·运维·服务器·bash·终端
mucheni3 小时前
迅为RK3568开发板OpeHarmony学习开发手册-修改应用程序名称
linux·前端·学习
CS_浮鱼3 小时前
【Linux】进程间通信
linux·运维·数据库
Altair12313 小时前
实验6 基于端口和域名的虚拟主机
linux·运维·服务器·云计算
爱和冰阔落3 小时前
【Linux工具链】编译效率革命:条件编译优化+动静态库管理+Makefile自动化,解决多场景开发痛点
linux·运维·自动化
wa的一声哭了3 小时前
WeBASE管理平台部署-WeBASE-Web
linux·前端·网络·arm开发·spring boot·架构·区块链
Shylock_Mister4 小时前
ARM与x86交叉编译实战排错指南
linux·c语言·arm开发
敲上瘾4 小时前
MySQL事务全攻略:ACID特性、隔离级别与并发控制
linux·数据库·mysql·安全