Jenkins+Gitea搭建CI/CD自动化+代码迁移(离线环境)
基础环境信息
服务器ip:
192.168.253.129
192.168.253.137
环境:Kylin v10 Jenkins:jenkins:2.541.2-lts Gitea:gitea:1.21.4 Nodejs:v20.19.0 yarn:yarn-v1.22.22 jdk:jdk-17.0.9 docker、docker-compose 注:由于是离线环境、所以以上都需要准备好二进制安装包 或者从有网环境导出docker镜像、下面会提供一个/etc/docker/daemon.json国内镜像加速json { "registry-mirrors": [ "https://docker.mirrors.ustc.edu.cn", "https://hub-mirror.c.163.com" ], "insecure-registries": [], "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2" }
1.环境准备
192.168.253.129 项目根目录:/app jenkins映射目录:/usr/docker/jenkins_data #时间同步 ntpdate ntp.aliyun.com #jdk17安装 cd /app tar xf ibm-semeru-open-jdk_x64_linux_17.0.9_9_openj9-0.41.0.tar.gz vim /etc/profile export JAVA_HOME=/app/jdk-17.0.9 export PATH=$JAVA_HOME/bin:$PATH source /etc/profile java -version验证#docker、jenkins安装 官网安装 docker-24.0.9.tgz tar -xvf docker-24.0.9.tgz cp docker/* /usr/bin/ vi /etc/systemd/system/docker.service systemctl daemon-reload systemctl start docker systemctl enable docker docker run -d -p 8082:8080 -p 50000:50000 --dns 8.8.8.8 --dns 114.114.114.114 -v /usr/docker/jenkins_data:/var/jenkins_home -v /etc/localtime:/etc/localtime:ro -v /usr/bin/docker:/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock -e JAVA_OPTS="-Duser.timezone=Asia/Shanghai" --restart=on-failure -u 0 --name myjenkins jenkins/jenkins:2.541.2-lts docker logs查看密码 #我事先在有网环境,把需要的插件都安装了,然后直接把plugins目录打包,拷贝到离线环境对应的目录中即可 unzip plugins.zip -d /usr/docker/jenkins_data/plugins/ #这里跑起来之后就可以访问ip:8082访问了 进去之后不装自定义插件 直接跳过 配置需要等maven node这些装好了在去网页调#maven安装 cd /app/ mkdir maven cd maven && tar xf apache-maven-3.9.12-bin.tar.gz \cp -r /app/maven/apache-maven-3.9.12 /usr/docker/jenkins_data/ vim /etc/profile export MAVEN_HOME=/app/maven/apache-maven-3.9.12 export PATH=${MAVEN_HOME}/bin:${PATH} source /etc/profile vi /usr/docker/jenkins_data/apache-maven-3.9.12/conf/settings.xml <!-- localRepository | The path to the local repository maven will use to store artifacts. | | Default: ${user.home}/.m2/repository <localRepository>/path/to/local/repo</localRepository> --> <localRepository>/var/jenkins_home/maven_repository</localRepository> ##由于是离线环境 这里需要先在本地把后端代码maven一遍得到repository文件夹 然后zip过来 电脑目录:C:\Users\pc2\.m2\repository cd /usr/docker/jenkins_data/ && mkdir maven_repository && cd maven_repository unzip repository.zip mv repository maven_repository#nodejs、yarn安装 node_modules迁移 cd /app tar xf node-v20.19.0-linux-x64.tar.gz mv node-v20.19.0-linux-x64 node-v20.19.0 vi /etc/profile export NODE_HOME=/app/node-v20.19.0 export PATH=$NODE_HOME/bin:$PATH source /etc/profile node -v npm -v cp -r /app/node-v20.19.0 /usr/docker/jenkins_data/ #node_modules 需要在本地电脑 npm运行一次然后将这个目录zip cd /usr/docker/jenkins_data/ tar xf yarn-v1.22.22.tar.gz docker exec -it -u root myjenkins ln -s /var/jenkins_home/yarn-tool/bin/yarn /usr/local/bin/yarn docker exec -it myjenkins yarn -v docker exec -it -u root myjenkins ln -s /var/jenkins_home/node-v20.19.0/bin/node /usr/local/bin/node docker exec -it -u root myjenkins ln -s /var/jenkins_home/node-v20.19.0/bin/npm /usr/local/bin/npm docker exec -it myjenkins yarn -v mkdir -p /usr/docker/jenkins_data/frontend_cache/node_modules cd frontend_cache/node_modules/ unzip node_modules.zip
2.jenkins配置
#全局工具配置 #别名自定义 无要求





#生成git服务器的公钥 #需要在jenkins服务器执行这个命令 并且ssh端口需要宿主机真实端口 [root@Kylin01 plugins]# ssh-keyscan -p 222 -t rsa 192.168.253.137 # 192.168.253.137:222 SSH-2.0-OpenSSH_9.3 [192.168.253.137]:222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCpfG5+2lizKDAhCXMXNvmYpRrloXCENzxwihKCWJ7HcfnLHNa+nTGCmmKbqYybn6XB63xeXAxUwj+Al1kHk9mDV28LOQ5o9sFPPKgE0vdHbvSvYTsYxgThFHR3XLnUj/TAasTZLPDkTQo0IP5PeKavy63B5RIIGyd0LH3NgiHbM3LyEr9mjuNr+tbygNrHkCjIye8bT/S8zp5q3y7kclLMUynCLJNEydefqITj2rNU2IqKYoWumCB1G9sFQbKLuPlqu6TU41zJ4n1lQEe/JcCOl+BhJIxcJ3OhEee8dbLYfiuqx3UQGbEswjSSfKZVQb/AcyWZu/1uytNLBaRDKOfm/lcjunQhbaPPIpt2TeYkTgLn3yfPrzQ2S1TJcTI4+cyn0e7teWdMlGOSCCkXCm0bSl9qk1IKeaMMHJ94aclMd6lWBn8qDgwKOtyvJfRDYeZTcv7Ai6YZRYwGH3W81RIg+hBoJyrt0OaYVmLhMOO0rr6aHxz+TD633RWpBjz12Ic=

#设置凭据 这里获取的是jenkins服务器的私钥 同时后面gitea服务器也要设置对应同一套的公钥 [root@Kylin01 plugins]# docker exec -it myjenkins bash [root@Kylin01 plugins]# ssh-keygen -t rsa -b 4096 root@49413caa42b7:/# cat /root/.ssh/id_rsa root@49413caa42b7:/# cat /root/.ssh/id_rsa.pub


#流水线job配置 后端job的tigger配置



前端job的tigger配置 为了识别json


#后端Pipeline scripts pipeline { agent any tools { // 请确保在 Jenkins "Global Tool Configuration" 中配置了名为 'maven-3.9.12' 的 Maven maven 'maven-3.9.12' } triggers { pollSCM('') } environment { // ================= 配置区 ================= // 1. 目标宿主机信息 (用于部署) REMOTE_IP = "192.168.253.137" DEPLOY_PORT = "22" // 宿主机 SSH 端口 REMOTE_USER = "root" REMOTE_DIR = "/app/xhdj_dev/project_backend" // 2. Gitea 信息 (仅用于拉取代码) GITEA_PORT = "222" // Gitea 容器映射端口 GITEA_CRED = "gitea-ssh-key" // Jenkins 中配置的凭据 ID // 3. 待发布的模块列表 WHITELIST = "zhdq-auth-web zhdq-gateway zhdq-service-datamiddle-web zhdq-service-file zhdq-service-jobhandle zhdq-service-party-manage-web zhdq-service-party-meeting-web zhdq-service-party-member-web zhdq-service-xxl" // 4. 需要检测存活的端口 CHECK_PORTS = "10200 10005 10206 13800 8012 10204 10203 28305" // ========================================== } stages { stage('拉取代码') { steps { echo "🚚 正在从 Gitea 拉取代码..." git credentialsId: "${GITEA_CRED}", url: "ssh://git@${REMOTE_IP}:${GITEA_PORT}/liaoch_1/xh_backend.git", branch: 'main' } } stage('离线编译') { steps { echo "🔨 开始 Maven 编译 (离线模式)..." // -o 为离线模式,如果是第一次编译请去掉 -o sh 'mvn clean package -DskipTests -o -s /var/jenkins_home/apache-maven-3.9.12/conf/settings.xml -Dmaven.repo.local=/var/jenkins_home/maven_repository' } } stage('收集并远程推送') { steps { sh ''' #!/bin/bash set -e echo "📂 正在确保远程目录存在: ${REMOTE_DIR}" ssh -p ${DEPLOY_PORT} ${REMOTE_USER}@${REMOTE_IP} "mkdir -p ${REMOTE_DIR}" echo "🔍 开始扫描并推送 JAR 包..." for mod in $WHITELIST; do # 查找生成的 jar,排除 sources 和 javadoc jar_path=$(find . -path "*/target/${mod}*.jar" ! -name "*-sources.jar" ! -name "*-javadoc.jar" -type f | head -n 1) if [ -n "$jar_path" ]; then echo "✅ 匹配成功: $mod -> 正在推送..." # 注意:scp 端口是大写 -P scp -P ${DEPLOY_PORT} "$jar_path" "${REMOTE_USER}@${REMOTE_IP}:${REMOTE_DIR}/${mod}.jar" else echo "⚠️ 未找到模块: $mod 的 JAR 文件" fi done ''' } } stage('远程重启并存活检测') { steps { sh ''' #!/bin/bash ssh -p ${DEPLOY_PORT} ${REMOTE_USER}@${REMOTE_IP} " cd ${REMOTE_DIR} echo '🚀 执行重启脚本...' ./app-manager-linux-amd64 restart echo '⏳ 进入 120 秒初始化等待期...' sleep 120 echo '🔍 开始进行端口健康检查...' FAILED_COUNT=0 for port in ${CHECK_PORTS}; do # 同时尝试 ss 和 netstat 增加兼容性 if ss -lnt | grep -q \\":\$port \\" || netstat -lnt | grep -q \\":\$port \\"; then echo \\"✅ [OK] 端口 \$port 正常启动\\" else echo \\"❌ [ERROR] 端口 \$port 未响应!\\" FAILED_COUNT=\$((FAILED_COUNT+1)) fi done if [ \$FAILED_COUNT -gt 0 ]; then echo \\"------------------------------------------\\" echo \\"❌ 部署失败:共有 \$FAILED_COUNT 个模块未正常启动!\\" echo \\"------------------------------------------\\" exit 1 else echo \\"------------------------------------------\\" echo \\"🎊 部署成功:所有微服务均已就绪!\\" echo \\"------------------------------------------\\" fi " ''' } } } post { always { echo "🏁 流程结束。" } failure { echo "❌ 构建失败,请检查 Jenkins 控制台输出和服务器日志。" } } }
#前端Pipeline scripts pipeline { agent any environment { // 目标部署服务器信息 (137 宿主机) REMOTE_IP = "192.168.253.137" REMOTE_USER = "root" // 生产环境目录 PROD_DIR = "/app/xhdj_dev/project_frontend" // 备份/归档目录 UPDATE_DIR = "/app/xhdj_dev/project_update/frontend_${BUILD_NUMBER}" // Jenkins 凭据 ID (请确保在 Jenkins 凭据里配置了私钥,且 ID 为此值) GITEA_CRED = "gitea-ssh-key" } triggers { // 只要 UI 界面配置了 token,脚本里加这段可以确保配置被固化 GenericTrigger( genericVariables: [ [key: 'ref', value: '$.ref'] ], token: 'xh_frontend_token', causeString: 'Gitea Push: $ref', printPostContent: true, silentResponse: false ) } stages { stage('Git Checkout') { steps { echo "🚚 正在从 Gitea 拉取前端代码..." // 修正后的地址:使用 222 端口和 xh_frontend 仓库 git credentialsId: "${GITEA_CRED}", url: "ssh://[email protected]:222/liaoch_1/xh_frontend.git", branch: 'main' } } stage('Front-end Build') { steps { echo "🛠️ 正在执行离线构建..." sh """ # 1. 环境变量(必须加,否则找不到 node/yarn) export NODE_HOME="/var/jenkins_home/node-v20.19.0" export YARN_HOME="/var/jenkins_home/yarn-tool" export PATH="\$NODE_HOME/bin:\$YARN_HOME/bin:\$PATH" # 2. 注入依赖 CACHE_DIR="/var/jenkins_home/frontend_cache/node_modules" if [ -d "\$CACHE_DIR" ]; then echo "📦 正在注入 node_modules..." # cp -rn 确保只拷贝缺少的文件,不重复覆盖 cp -rn \$CACHE_DIR ./ else echo "❌ 找不到离线依赖目录" && exit 1 fi # 3. 修复 tyarn 找不到的问题 # 将 package.json 里的 "tyarn" 替换为 "yarn" if grep -q "tyarn" package.json; then sed -i 's/tyarn/yarn/g' package.json fi # 4. 执行构建 yarn build """ } } stage('Archive & Deploy') { steps { echo "🚀 正在同步产物到 137 服务器 (精准模式)..." sh """ # 1. 确保远程目录存在 ssh -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_IP} "mkdir -p ${UPDATE_DIR} ${PROD_DIR}" # 2. 【核心修正】只传输内层真正的产物 # 注意这里的路径:dist/project_frontend/* echo "📦 正在从 dist/project_frontend 提取文件..." scp -r dist/project_frontend/* ${REMOTE_USER}@${REMOTE_IP}:${UPDATE_DIR}/ # 3. 部署到生产目录 # 先清空,再用 /. 语法平铺拷贝 ssh ${REMOTE_USER}@${REMOTE_IP} " rm -rf ${PROD_DIR}/* && \ cp -Rf ${UPDATE_DIR}/. ${PROD_DIR}/ && \ echo '✅ 部署成功!目录内容:' && \ ls -F ${PROD_DIR} " """ } } stage('Health Check') { steps { echo "🔍 检查 137 服务器上的部署结果..." sh "ssh ${REMOTE_USER}@${REMOTE_IP} 'ls -l ${PROD_DIR}'" } } } post { success { echo "✅ 前端自动部署成功!" } failure { echo "❌ 构建失败,请查看 Console Output。" } } }
3.gitea配置
#安装docker gitea tar xf docker-24.0.9.tgz cp docker/* /usr/bin/ vi /etc/systemd/system/docker.service systemctl daemon-reload systemctl enable docker systemctl start docker cp docker-compose-linux-x86_64 /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose docker-compose version cd /opt [root@Kylin01 gitea]# vim docker-compose.yml version: "3" networks: gitea: external: false services: server: image: docker.gitea.com/gitea:1.21.4 # 建议使用稳定版,1.25目前可能过于超前 container_name: gitea environment: - USER_UID=1000 - USER_GID=1000 # 如果你以后想用 MySQL/PostgreSQL,可以在这里加环境变量 restart: always networks: - gitea volumes: - ./gitea:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro ports: - "3000:3000" # Web 访问端口 - "222:22" # SSH 端口 id was chown -R was. /opt/gitea export DOCKER_API_VERSION=1.43 docker-compose up -d vim gitea/conf/app.ini [webhook] ALLOWED_HOST_LIST = * SKIP_TLS_VERIFY = true DELIVER_TIMEOUT = 15s docker restart gitea #初始化项目目录 mkdir -p /app/xhdj_dev cd /app/xhdj_dev chmod +x app-manager-linux-amd64 ./app-manager-linux-amd64 init#gitea 代码仓库初始化 1.拉取需要迁移的前后端代码 先拉到本地电脑对应两个目录 git clone http://***.git 2.在git新建两个仓库 3.拿到仓库地址 http://192.168.253.137:3000/liaoch_1/xh_frontend.git http://192.168.253.137:3000/liaoch_1/xh_backend.git 4.将拉下来的代码推送上去 git push --mirror http://192.168.253.137:3000/liaoch_1/xh_frontend.git git push --mirror http://192.168.253.137:3000/liaoch_1/xh_backend.git #webhook设置 前端:http://192.168.253.129:8082/generic-webhook-trigger/invoke?token=xh_frontend_token 后端:http://192.168.253.129:8082/generic-webhook-trigger/invoke?token=xh_backend_token(这里的tocken就是前面jenkins的tigger里定义的) #ssh秘钥设置 就是前面在jenkins容器中获取到的pub公钥 root@49413caa42b7:/# cat /root/.ssh/id_rsa.pub




4.测试推送
#gitea测试推送 然后去jenkins下看是否有任务构建

#推送代码测试 1.本地电脑修改部分代码 2.目录终端执行 git add . git commit -m "测试 Webhook 自动触发构建" git push origin main 3.查看jenkins是否有新的任务构建 4.检验是否构建成功 5.查看对应项目目录下是否有构建成功的jar包 前端文件 后端应用是否成功启动
