centos8 jenkins 搭建和使用

一、安装jenkins

  1. 直接war包搭建下载地址:https://get.jenkins.io/war-stable/
    下载稳定长期版本

二、jenkins 启动依赖java, 安装java sdk ,好像支持java 11和17版本,21版本不支持会报错

  1. 下载sdk地址,https://www.oracle.com/java/technologies/downloads/#java17
  2. 解压并且添加环境变量
sh 复制代码
tar -xzf jdk-17_linux-x64_bin.tar.gz -C /usr/local/
在/etc/profile 添加
export JAVA_HOME=/usr/local/jdk-17.0.8
export PATH=$PATH:$JAVA_HOME/bin

source /etc/profile
java -version

三、启动jenkins

1.启动命令
sh 复制代码
java -jar jenkins.war --httpPort=9090

启动完成后,会生成首次登录的秘钥,一般会在
cat /root/.jenkins/secrets/initialAdminPassword

我使用的github ,在github 配置 ssh 公钥 ,位置setting ssh,在jenkins 配置全局私钥

服务器生成密钥

复制代码
ssh-keygen -t rsa

注意在页面拉取代码的时候Are you sure you want to continue connecting (yes/no/[fingerprint])? yes,需要点击确认

2.添加到system 守护进程去运行
sh 复制代码
[Unit]
Description=Jenkins Daemon
After=network.target

[Service]
User=jenkins
Group=jenkins
Type=simple
ExecStart=/usr/local/jdk-17.0.8/bin/java -jar /root/jenkins.war --httpPort=9099
Restart=always

[Install]
WantedBy=multi-user.target

设置启动和开启启动

复制代码
sudo systemctl daemon-reload
启动 Jenkins: sudo systemctl start jenkins
停止 Jenkins: sudo systemctl stop jenkins
开机启动 Jenkins: sudo systemctl enable jenkins
查看 Jenkins 服务状态: sudo systemctl status jenkins
日志 sudo journalctl -u jenkins

四、继续安装docker

sh 复制代码
yum remove docker  docker-common docker-selinux docker-engine

yum install -y yum-utils device-mapper-persistent-data lvm2

选择镜像
阿里云镜像
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
源镜像
yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo
调试容器出错原因
docker run -it --rm -p 8062:8062 \
-v $(pwd)/config.yaml:/app/conf/config.yaml \
-v $(pwd)/logs:/app/logs \
gitxuzan/weather_api:v0.0.1 /bin/sh
sh 复制代码
查看服务端:
yum list docker-ce --showduplicates | sort -r
选择版本安装

查看客户端,下载对应版本
yum list docker-ce-cli --showduplicates | sort -r

yum install -y docker-ce-3:20.10.9-3.el8 docker-ce-cli-1:20.10.9-3.el8
最后开启启动查看
systemctl start docker
systemctl enable docker docker version

五、设置跳板机登录

.ssh/config文件配置

执行 ssh target 可以跳板机登录

复制代码
# 定义跳板机 (a) 的配置
Host bastion
    # 跳板机的IP地址或主机名
    HostName 16.xxx.xxx.xx
    # 用于登录跳板机的用户名
    User xuzan
    # Jenkins 服务器上的SSH私钥路径,用于身份验证
    IdentityFile /var/lib/jenkins/.ssh/bastonhost_16.xxx.xxx.pem

# 定义目标服务器 (b) 的配置
Host target
    # 目标服务器的IP地址或主机名
    HostName 52.xxx.xxx.xxx
    # 用于登录目标服务器的用户名
    User ec2-user
    # Jenkins 服务器上的SSH私钥路径,用于身份验证
    IdentityFile /home/xuzan/.ssh/news_app.pem
    # 使用ProxyCommand来指定通过跳板机连接到目标服务器
    # 这里使用ssh命令通过跳板机连接到目标服务器
    ProxyCommand ssh -q -W %h:%p bastion

六、jenkins 流水线,监听到push,然后根据commit 信息打包

sh 复制代码
pipeline {
    agent any
    options {
        disableConcurrentBuilds()  // 确保流水线不会并行执行
        timeout(time: 5, unit: 'MINUTES')  // 设置整个流水线的超时为 5 分钟
    }

    environment {
        CRAWLER_API = "weather_api"
        DIR_RUN = "cd /home/ec2-user/data/docker/services/weather && ./secrets.sh"
        CREDENTIALSID = "f2b9ffa0-89d4-41bd-b3b4-9d5fd3cfac06"
        VERSION_FILE = 'deployed_version.txt'
    }

    stages {

        stage('Retrieve Latest Successful Version') {
            steps {
                script {
                    if (fileExists(env.VERSION_FILE)) {
                        def versions = readFile(file: env.VERSION_FILE).trim().split("\n")
                        env.LATEST_VERSION = versions[-1] // Last line is the latest version
                        env.PREVIOUS_VERSION = versions.size() > 1 ? versions[-2] : "v0.0.1" // Second last line is the previous version
                    } else {
                        env.LATEST_VERSION = "v0.0.1"
                        env.PREVIOUS_VERSION = "v0.0.1"
                    }
                }
            }
        }


        stage('Checkout Code from GitHub') {
            steps {
                checkout([
                    $class: 'GitSCM',
                    branches: [[name: '*/main']],
                    extensions: [],
                    userRemoteConfigs: [[url: "git@github.com:xxxxx/${CRAWLER_API}.git", credentialsId: "${CREDENTIALSID}"]]
                ])
            }
        }

        stage('Decide Operation Based on Commit Message') {
            steps {
                script {
                    def lastCommitMessage = sh(script: "git log -1 --pretty=%B", returnStdout: true).trim()
                    env.CommitMessage = lastCommitMessage
                    if (lastCommitMessage.startsWith("#pro")) {
                        env.OPERATION = "deploy"
                        env.VERSION = "v0.0.${env.BUILD_NUMBER}"
                    } else if (lastCommitMessage.startsWith("#pre")) {
                        env.OPERATION = "rollback"
                        env.VERSION = env.PREVIOUS_VERSION
                    } else {
                        currentBuild.result = 'ABORTED'
                        error("Invalid commit message. Either start with #pro for deploy or #pre for rollback!")
                    }
                }
            }
        }

        stage('Build Docker Image and Push') {
            when {
                expression { env.OPERATION == "deploy" }
            }
            steps {
                script {
                    sh 'docker build --platform linux/amd64 -t xxxx/${CRAWLER_API}:${VERSION} -f Dockerfile_amd64_arm64 .'
                    sh 'docker push xxxx/${CRAWLER_API}:${VERSION}'
                }
            }
        }

        stage('登录服务器Deploy/Rollback on Production Server') {
            steps {
                script {
                    sh 'ssh -t target "${DIR_RUN} ${VERSION}"'
                }
            }
        }

        stage('验证接口Verify Deployment') {
            steps {
                script {
                    sleep 5
                    sh """
                        status_code=\$(curl -o /dev/null -s -w "%{http_code}" https://xxxxx/weather/v1/app/test)
                        if [ "\$status_code" != "200" ]; then
                            echo "API check failed! Received status code: \$status_code"
                            exit 1
                        fi
                    """
                }
            }
        }
    }

    post {
        success {
            echo 'Build was successful!'
            script {
                if (env.OPERATION == "deploy") {
                // 如果文件存在且最后一个字符不是换行符,则追加一个换行符
                if (fileExists(env.VERSION_FILE) && sh(script: "tail -c 1 ${env.VERSION_FILE} | wc -l", returnStdout: true).trim() != "1") {
                    sh "echo '' >> ${env.VERSION_FILE}"
                }
                // 追加版本号
                    sh "echo '${VERSION}' >> ${env.VERSION_FILE}"
                }
                currentBuild.description = "构建成功!"
                def projectName = sh(script: "basename `git rev-parse --show-toplevel`", returnStdout: true).trim()
                def messageToSend = "${projectName}: ${VERSION} ${env.CommitMessage}"
                sh "ssh target '/home/ec2-user/data/docker/services/tg.sh \"构建成功 ${messageToSend}\"'"
            }
        }

        failure {
            echo 'Build failed!'
            script {
                currentBuild.description = "构建失败!"
                def projectName = sh(script: "basename `git rev-parse --show-toplevel`", returnStdout: true).trim()
                def messageToSend = "${projectName}: ${VERSION} ${env.CommitMessage}"
                sh "ssh target '/home/ec2-user/data/docker/services/tg.sh \"构建失败 ${messageToSend}\"'"
            }
        }

        aborted {
            echo '构建取消拉aborted!'
            script {
                currentBuild.description = "构建取消拉!"
            }
        }
    }
}
复制代码
获取构建方式,例如是push 的还是手动构建的,还是定时构建的
 environment {
    CAUSE = "${currentBuild.getBuildCauses()[0].shortDescription}"
}

其他

复制代码
github clone不下来

https://ping.chinaz.com/github.com

选择可用的ip ,在/etc/hosts 修改
20.205.243.166 github.com
20.205.243.166 raw.githubusercontent.com
相关推荐
大树883 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质3 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工3 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智3 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_3 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
施努卡机器视觉3 天前
SNK施努卡侧滑门锁上滑轮总成自动化装配线,从零件到组件,全流程精密制造方案
运维·自动化·制造
AC赳赳老秦3 天前
用 OpenClaw 搭建服务器故障应急响应系统,自动处理 80% 常见运维故障
android·运维·服务器·python·rxjava·deepseek·openclaw
java_cj3 天前
深入kube-apiserver认证机制:从Bearer Token到mTLS的完整认证链解析
linux·运维·服务器·云原生·容器·kubernetes
lsyeei3 天前
linux 系统目录详解
linux·运维·服务器