Jenkins CI/CD 实践:从构建到部署的完整指南

目录

  1. Jenkins Pipeline 配置
  2. Docker 镜像构建与推送
  3. Docker Compose 部署
  4. 前端项目部署
  5. SSH 密钥配置

Jenkins Pipeline 配置
关键配置要点
使用环境变量统一管理路径和凭据
配置 Maven 本地仓库路径,
加速构建 使用私有 Docker 仓库地址(不含http:// 协议)

基础环境配置

pipeline {    
	agent any    
	environment {        
		JAVA_HOME = "/data1/software/TencentKona-8.0.22-452"
		MAVEN_HOME = "/data1/software/apache-maven-3.9.10"        
		PATH = "${env.MAVEN_HOME}/bin:${env.JAVA_HOME}/bin:${env.PATH}"
		MAVEN_OPTS = "-Dmaven.repo.local=/data1/jenkins/maven-repo
		DOCKER_REGISTRY = ""
		DEPLOY_SERVER = "ip"
        DEPLOY_USER = ""
        SSH_CREDENTIALS_ID = ""
	}   
}

Docker 镜像构建与推送
Dockerfile 配置要点
[Podman 配置]
编辑配置文件sudo vi /etc/containers/registries.conf
添加配置[[registry]]location = "ip"insecure = true
[docker 配置]
编辑配置文件sudo vi /etc/docker/daemon.json
添加配置(注意:不要包含 http://){ “insecure-registries”: [“ip”]}
重启 Dockersudo systemctl restart docker

多模块构建脚本

stage('Build and Push Docker Images'){
    steps{
        script {
            def modules = [
                ['common-gateway', 'xq/common-gateway-v2'],
                ['common-auth', 'xq/common-auth-v2'],
                ['common-connector', 'xq/common-connector-v2'],
                ['shuduoduo-ims', 'xq/shuduoduo-ims-v2']
            ]
            for (module in modules) {
                def moduleDir = module[0]
                def imageName = module[1]
                buildDockerImage(moduleDir, imageName)
                pushDockerImage(imageName)
            }
        }
    }
}
def buildDockerImage(String moduleDir,String imageName){
    dir(moduleDir){
        sh """
            docker build -t ${env.DOCKER_REGISTRY}/${imageName}:1.0 .
        """
    }
}
def pushDockerImage(String imageName) {
    sh """
        docker push ${env.DOCKER_REGISTRY}/${imageName}:1.0
    """
}

Docker Compose 部署
关键要点
先 down 再 up,确保使用新镜像
使用 docker compose(v2)而非 docker-compose
分别查看各服务日志,便于排查问题

部署脚本

def deployWithDockerCompose() {
    withCredentials([sshUserPrivateKey(
        credentialsId: env.SSH_CREDENTIALS_ID,
        keyFileVariable: 'KEY_FILE',
        usernameVariable: 'SSH_USER'
    )]) {
        sh '''
            ssh -i "$KEY_FILE" -o StrictHostKeyChecking=no "$SSH_USER@$DEPLOY_SERVER" bash -s << 'ENDSSH'
                set -e
     
                COMPOSE_FILE="/data/xq/docker-compose.yml"
                
                if [ ! -f "$COMPOSE_FILE" ]; then
                  echo "ERROR: Compose file not found: $COMPOSE_FILE"
                  exit 1
                fi
             
                cd "$(dirname "$COMPOSE_FILE")"
                
                # 使用 docker compose v2
                docker compose -f "$COMPOSE_FILE" pull
                docker compose -f "$COMPOSE_FILE" down
                docker compose -f "$COMPOSE_FILE" up -d --remove-orphans
                
                sleep 10
                docker compose -f "$COMPOSE_FILE" ps
                
                # 分别查看每个服务的日志
                for s in $(docker compose -f "$COMPOSE_FILE" config --services); do
                  echo "---- $s ----"
                  docker compose -f "$COMPOSE_FILE" logs --tail=20 "$s" || true
                done
ENDSSH
        '''
    }
}

前端项目部署

前端构建与部署 Pipeline

pipeline {
    agent any

    environment {
        NODE_HOME = "/data1/software/node-v18.16.0-linux-x64"
        PATH = "${NODE_HOME}/bin:${env.PATH}"
        DEPLOY_SERVER = "ip"
        DEPLOY_USER = ""
        SSH_CREDENTIALS_ID = ""
    }

    stages {
        stage('Checkout Code') {
            steps {
                git branch: 'main', credentialsId: 'xxx', url: 'git@xxx.git'
            }
        }

        stage('Install') {
            steps {
                sh 'npm install'
            }
        }
        
        stage('Build') {
            steps {
                sh 'BROWSERSLIST_IGNORE_OLD_DATA=true DISABLE_ESLINT_PLUGIN=true npm run build:prod'
            }
        }
        
        stage('Package') {
            steps {
                sh '''
                    rm -f build.tar.gz
                    tar -C build -czf build.tar.gz .
                    ls -lh build.tar.gz
                '''
            }
        }
        
        stage('Upload') {
            steps {
                withCredentials([sshUserPrivateKey(
                    credentialsId: env.SSH_CREDENTIALS_ID,
                    keyFileVariable: 'KEY_FILE',
                    usernameVariable: 'SSH_USER'
                )]) {
                    sh '''
                        scp -i "$KEY_FILE" -o StrictHostKeyChecking=no \
                            build.tar.gz "$SSH_USER@$DEPLOY_SERVER:/data/xq-web/build.tar.gz"
                    '''
                }
            }
        }
        
        stage('Deploy') {
            steps {
                withCredentials([sshUserPrivateKey(
                    credentialsId: env.SSH_CREDENTIALS_ID,
                    keyFileVariable: 'KEY_FILE',
                    usernameVariable: 'SSH_USER'
                )]) {
                    sh '''
                        ssh -i "$KEY_FILE" -o StrictHostKeyChecking=no \
                            "$SSH_USER@$DEPLOY_SERVER" bash -s << 'ENDSSH'
                            set -e
                            cd /data/xq-web
                            
                            mkdir -p backup build html
                            
                            # 备份当前版本
                            TS=$(date +%Y%m%d%H%M%S)
                            if [ -f "build.tar.gz" ]; then
                                mv build.tar.gz "backup/build_${TS}.tar.gz"
                            fi
                            
                            # 解压新版本
                            rm -rf build/*
                            tar -xzf build.tar.gz -C build/
                            
                            # 部署到html目录
                            rm -rf html/*
                            cp -a build/. html/
                            
                            echo "部署完成"
ENDSSH
                    '''
                }
            }
        }
    }
}

生成 SSH 密钥

 #生成 ed25519 密钥(推荐)
 ssh-keygen -t ed25519 -C "jenkins-deploy" -f ~/.ssh/jenkins_deploy_key 
 #或生成 RSA 密钥(兼容性更好)
 ssh-keygen -t rsa -b 4096 -C "jenkins-deploy" -f ~/.ssh/jenkins_deploy_key

在 Jenkins 中配置 SSH 凭据

	进入 Manage Jenkins → Credentials
	添加 SSH 凭据:
	Kind: SSH Username with private key
	Username: 部署服务器的用户名
	Private Key: 选择 Enter directly,粘贴私钥内容
	ID: 设置唯一标识符
	在目标服务器上配置 authorized_keys
	#确保目录和权限
	mkdir -p ~/.ssh
	chmod 700 ~/.ssh
	# 添加公钥
	echo "公钥内容" >> ~/.ssh/authorized_keys
	# 设置权限
	chmod 600 ~/.ssh/authorized_keys
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐