文章目录
Jenkins来构建一个Pipeline项目
我们来使用 Jenkins 来构建一个真实的Pipeline项目 进行演示
我们要创建一个Jenkinsfile
的文件 ,放在 git repo 项目根目录。
创建 Pipeline 项目任务
1 首先 在首页开始 选择 新建任务
2 新建任务, 填写任务名称, 以及选择流水线项目构建。
可以看到这里有很多选项, 自由风格,流水线,多配置项目等, 我认为流水线 比较灵活,通过 pipeline 脚本来控制比较方便,
自由风格 当然也是可以的, 自由不需要pipeline ,适合简单的发布场景, 我们这里 需要进行一些控制,后面还要和 K8S
打交道。
3 流水线的配置
点击OK 之后 ,进入 下面的配置页面,这里 找到 流水线的配置, 这里就是要配置 Pipeline 脚本来自哪里,
第一种: Pipeline script 这种方式 是把他卸载 下面的空白的地方, 这种方式, 方便我们来临时调试脚本。
第二种: Pipeline script from SCM, 选择一个git 代码仓库, 然后把 Jenkinfile
放在 代码仓库里面,这样可以维护这个文件,进行追踪 变化等。建议也是要放到 repo 里面,这也是官方建议的做法。
作为演示 我来演示这两种方式
先来第一种: 直接把脚本 粘贴在空白处
我准备好了脚本 Jenkinsfile 脚本
environment
这个块中定义了一些变量。
DOCKER_REGISTRY
这个你需要一个 可以推送镜像的仓库,可以自己搭建.
GIT_URL
git 地址 要填写真实地址,
CREDENTIALS_ID
凭据ID , 是要 创建出来,用来拉取代码的凭据。
IMAGE_NAME
打包后 放在image路径里面。
CREDENTIALS_ID 如何创建呢?
系统管理 > 凭据
凭据的类型 有很多种选一个你认证的方式, 这个用来 去拉取 git repo 的权限用到的。
创建完成后,就可以看到 这个凭据ID, 这个ID 就是这样生成的。
pipeline {
agent any
environment {
// 定义全局环境变量
// 私有仓库地址
DOCKER_REGISTRY = 'xxx.xx.xx.xxx:12300'
IMAGE_NAME = 'saas-cloud-job-service'
SHORT_NAME = 'cloud-job'
// 填写 git repo 地址
GIT_URL = 'http://git.aaabbb.com/xxx/xxxxxxx/saas-cloud-job-service.git'
// 拉取代码的凭据ID
CREDENTIALS_ID = '080912b9-902a-49f1-89e1-4684586ab238'
}
parameters {
choice(name: 'BRANCH', choices: ['cicd','dev', 'test', 'master'], description: 'Select the branch to build')
choice(name: 'ENV', choices: ['test', 'prod'], description: 'Select the environment to deploy')
}
stages {
stage('Pull code') {
steps {
script {
// 使用参数化的分支名称进行 checkout
def branchName = params.BRANCH
checkout scmGit(
branches: [[name: "*/${branchName}"]],
extensions: [],
userRemoteConfigs: [[credentialsId: CREDENTIALS_ID, url: GIT_URL]]
)
}
}
}
stage('Build project') {
steps {
script {
def branchName = params.BRANCH
env.branchName = branchName // 设置环境变量
// 获取 Git SHA 和当前日期
def gitSha = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
def currentDate = sh(returnStdout: true, script: 'date +%Y%m%d').trim()
// 构建 Docker 镜像标签
env.IMAGE_TAG = "${DOCKER_REGISTRY}/${IMAGE_NAME}/${SHORT_NAME}:${branchName}-${currentDate}-${gitSha}"
// 打印信息
// echo "Building Docker image with tag: ${env.IMAGE_TAG}"
// 构建 Docker 镜像
sh """
echo " ============================= 开始构建docker image ============================= "
docker build -f Dockerfile . -t ${env.IMAGE_TAG}
echo " ============================= docker image 构建完成 ============================= "
echo "[TAG]: ${env.IMAGE_TAG}"
"""
}
}
}
stage('Push Docker image') {
steps {
script {
// 登录并推送 Docker 镜像
dockerLoginAndPush(env.IMAGE_TAG)
}
}
}
stage('Deploy project') {
steps {
echo 'Publishing project'
// 这里可以添加部署的具体步骤
}
}
}
post {
always {
echo 'This pipeline will always run, begin cleaning workspace.'
cleanWs()
}
success {
echo 'The pipeline succeeded.'
}
failure {
echo 'The pipeline failed.'
}
changed {
echo 'The pipeline status has changed.'
}
}
}
def dockerLoginAndPush(String imageTag) {
/**
使用 withDockerRegistry 插件来简化 Docker 登录和推送
*/
withDockerRegistry([credentialsId: 'docker-harbor-registry-credentials', url: "http://${env.DOCKER_REGISTRY}"]) {
try {
// 推送 Docker 镜像
sh "docker push ${imageTag}"
echo "Pushed Docker Image [TAG]: ${imageTag}"
} catch (err) {
error "Failed to push Docker image: ${err}"
}
}
}
parameters
解释一下 这个块的作用 ,这里定义两个参数,BRANCH ,ENV 方便来选, 从哪个分支来构建,发布到哪个分支。
stages
整个发布流程的阶段 ,这里定义 四个阶段。 每个阶段 会有 steps 下面 会有脚本,表示这个阶段 有步骤 要执行哪些脚本等。
post
表示发布完成后,做的动作,成功,失败之后 怎么处理等。
dockerLoginAndPush
封装了一个函数 方便 用来推送镜像。
4 把脚本粘贴进行保存
4-2 使用Jenkinsfile 来构建
这里选 Pipeline script from SCM ,
然后选择 Repositories URL , 然后选择 Credentials
4-3 回到任务列 ,点击立即构建
构建第一次 的时候, 直接cancel一下, 然后第二次构建。
第二次构建的时候 你可以发现,界面变了,就是 parameters
生效了, 我们选择 对应的分支以及要发布的环境 ,进行发布。
点击构建就可以了。
5 构建结果分析
点击 #2
的位置,就可以看到 构建日志,有时候 就是根据构建日志来排查问题。
完整的日志复制下来 如下:
2025-03-15 17:50:14 Started by user admin
2025-03-15 17:50:15 [Pipeline] Start of Pipeline
2025-03-15 17:50:15 [Pipeline] node
2025-03-15 17:50:15 Running on Jenkins in /mnt/var/lib/jenkins/workspace/test-job-demo
2025-03-15 17:50:15 [Pipeline] {
2025-03-15 17:50:15 [Pipeline] withEnv
2025-03-15 17:50:15 [Pipeline] {
2025-03-15 17:50:15 [Pipeline] stage
2025-03-15 17:50:15 [Pipeline] { (Pull code)
2025-03-15 17:50:15 [Pipeline] script
2025-03-15 17:50:15 [Pipeline] {
2025-03-15 17:50:15 [Pipeline] checkout
2025-03-15 17:50:15 The recommended git tool is: NONE
2025-03-15 17:50:15 using credential 080912b9-902a-49f1-89e1-4684586ab238
2025-03-15 17:50:15 Cloning the remote Git repository
2025-03-15 17:50:15 Cloning repository http://gitee.aaa.com/xxx/xxxx-xxxxx/saas-cloud-job-service.git
2025-03-15 17:50:15 > /usr/local/git/git-2.43.0/git init /mnt/var/lib/jenkins/workspace/test-job-demo # timeout=10
2025-03-15 17:50:15 Fetching upstream changes from http://gitee.aaa.com/xxx/xxxx-xxxxx/saas-cloud-job-service.git
2025-03-15 17:50:15 > /usr/local/git/git-2.43.0/git --version # timeout=10
2025-03-15 17:50:15 > git --version # 'git version 2.43.0'
2025-03-15 17:50:15 using GIT_ASKPASS to set credentials gitlab-auth-user-password
2025-03-15 17:50:15 > /usr/local/git/git-2.43.0/git fetch --tags --force --progress -- http://gitee.aaa.com/xxx/xxxx-xxxxx/saas-cloud-job-service.git +refs/heads/*:refs/remotes/origin/* # timeout=10
2025-03-15 17:50:16 > /usr/local/git/git-2.43.0/git config remote.origin.url http://gitee.aaa.com/xxx/xxxx-xxxxx/saas-cloud-job-service.git # timeout=10
2025-03-15 17:50:16 > /usr/local/git/git-2.43.0/git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
2025-03-15 17:50:16 Avoid second fetch
2025-03-15 17:50:16 > /usr/local/git/git-2.43.0/git rev-parse refs/remotes/origin/master^{commit} # timeout=10
2025-03-15 17:50:16 Checking out Revision 1f0345adcfc8f98731c8452fa70d034e60e79417 (refs/remotes/origin/master)
2025-03-15 17:50:16 > /usr/local/git/git-2.43.0/git config core.sparsecheckout # timeout=10
2025-03-15 17:50:16 > /usr/local/git/git-2.43.0/git checkout -f 1f0345adcfc8f98731c8452fa70d034e60e79417 # timeout=10
2025-03-15 17:50:16 Commit message: "合并分支 'colin-0114' 到 'master'"
2025-03-15 17:50:16 First time build. Skipping changelog.
2025-03-15 17:50:16 [Pipeline] }
2025-03-15 17:50:16 [Pipeline] // script
2025-03-15 17:50:16 [Pipeline] }
2025-03-15 17:50:16 [Pipeline] // stage
2025-03-15 17:50:16 [Pipeline] stage
2025-03-15 17:50:16 [Pipeline] { (Build project)
2025-03-15 17:50:16 [Pipeline] script
2025-03-15 17:50:16 [Pipeline] {
2025-03-15 17:50:16 [Pipeline] sh
2025-03-15 17:50:16 + git rev-parse --short HEAD
2025-03-15 17:50:16 [Pipeline] sh
2025-03-15 17:50:16 + date +%Y%m%d
2025-03-15 17:50:16 [Pipeline] sh
2025-03-15 17:50:17 + echo ' ============================= 开始构建docker image ============================= '
2025-03-15 17:50:17 ============================= 开始构建docker image =============================
2025-03-15 17:50:17 + docker build -f Dockerfile . -t xxx.xx.xx.xxx:12300/saas-cloud-job-service/cloud-job:master-20250315-1f0345a
2025-03-15 17:50:17 #0 building with "default" instance using docker driver
2025-03-15 17:50:17
2025-03-15 17:50:17 #1 [internal] load build definition from Dockerfile
2025-03-15 17:50:17 #1 transferring dockerfile: 275B done
2025-03-15 17:50:17 #1 DONE 0.0s
2025-03-15 17:50:17
2025-03-15 17:50:17 #2 [internal] load .dockerignore
2025-03-15 17:50:17 #2 transferring context: 2B done
2025-03-15 17:50:17 #2 DONE 0.0s
2025-03-15 17:50:17
2025-03-15 17:50:17 #3 [auth] zhiexa-public/python:pull token for xxx.xx.xx.xxx:12300
2025-03-15 17:50:17 #3 DONE 0.0s
2025-03-15 17:50:17
2025-03-15 17:50:17 #4 [internal] load metadata for xxx.xx.xx.xxx:12300/zhiexa-public/python:3.10.13-slim-bullseye
2025-03-15 17:50:17 #4 DONE 0.1s
2025-03-15 17:50:17
2025-03-15 17:50:17 #5 [internal] load build context
2025-03-15 17:50:17 #5 transferring context: 415.52kB 0.0s done
2025-03-15 17:50:17 #5 DONE 0.0s
2025-03-15 17:50:17
2025-03-15 17:50:17 #6 [1/6] FROM xxx.xx.xx.xxx:12300/zhiexa-public/python:3.10.13-slim-bullseye@sha256:b1c82dbf6dfb5e52cf8f595c9b6881696e4a5e996e5146cb99e19c2228592b6a
2025-03-15 17:50:17 #6 resolve xxx.xx.xx.xxx:12300/zhiexa-public/python:3.10.13-slim-bullseye@sha256:b1c82dbf6dfb5e52cf8f595c9b6881696e4a5e996e5146cb99e19c2228592b6a 0.0s done
2025-03-15 17:50:17 #6 DONE 0.0s
2025-03-15 17:50:17
2025-03-15 17:50:17 #7 [2/6] WORKDIR /usr/src/app
2025-03-15 17:50:17 #7 CACHED
2025-03-15 17:50:17
2025-03-15 17:50:17 #8 [3/6] RUN mkdir /usr/src/app/logs
2025-03-15 17:50:17 #8 CACHED
2025-03-15 17:50:17
2025-03-15 17:50:17 #9 [4/6] COPY requirements.txt ./
2025-03-15 17:50:17 #9 CACHED
2025-03-15 17:50:17
2025-03-15 17:50:17 #10 [5/6] RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
2025-03-15 17:50:17 #10 CACHED
2025-03-15 17:50:17
2025-03-15 17:50:17 #11 [6/6] COPY . .
2025-03-15 17:50:17 #11 DONE 0.1s
2025-03-15 17:50:17
2025-03-15 17:50:17 #12 exporting to image
2025-03-15 17:50:17 #12 exporting layers 0.0s done
2025-03-15 17:50:17 #12 writing image sha256:67c8b72a89e186f32ac93e33c993a524ca3857b871a7813854e19773afe420e5 done
2025-03-15 17:50:17 #12 naming to xxx.xx.xx.xxx:12300/saas-cloud-job-service/cloud-job:master-20250315-1f0345a done
2025-03-15 17:50:17 #12 DONE 0.1s
2025-03-15 17:50:17 + echo ' ============================= docker image 构建完成 ============================= '
2025-03-15 17:50:17 ============================= docker image 构建完成 =============================
2025-03-15 17:50:17 + echo '[TAG]: xxx.xx.xx.xxx:12300/saas-cloud-job-service/cloud-job:master-20250315-1f0345a'
2025-03-15 17:50:17 [TAG]: xxx.xx.xx.xxx:12300/saas-cloud-job-service/cloud-job:master-20250315-1f0345a
2025-03-15 17:50:17 [Pipeline] }
2025-03-15 17:50:17 [Pipeline] // script
2025-03-15 17:50:17 [Pipeline] }
2025-03-15 17:50:17 [Pipeline] // stage
2025-03-15 17:50:17 [Pipeline] stage
2025-03-15 17:50:17 [Pipeline] { (Push Docker image)
2025-03-15 17:50:17 [Pipeline] script
2025-03-15 17:50:17 [Pipeline] {
2025-03-15 17:50:17 [Pipeline] withDockerRegistry
2025-03-15 17:50:17 Using the existing docker config file.
2025-03-15 17:50:17 Removing blacklisted property: auths
2025-03-15 17:50:17 $ docker login -u admin -p ******** http://xxx.xx.xx.xxx:12300
2025-03-15 17:50:17 WARNING! Using --password via the CLI is insecure. Use --password-stdin.
2025-03-15 17:50:17 WARNING! Your password will be stored unencrypted in /mnt/var/lib/jenkins/workspace/test-job-demo@tmp/a08f0084-94c3-405c-b3e5-c0135ff990db/config.json.
2025-03-15 17:50:17 Configure a credential helper to remove this warning. See
2025-03-15 17:50:17 https://docs.docker.com/engine/reference/commandline/login/#credentials-store
2025-03-15 17:50:17
2025-03-15 17:50:17 Login Succeeded
2025-03-15 17:50:17 [Pipeline] {
2025-03-15 17:50:17 [Pipeline] sh
2025-03-15 17:50:18 + docker push xxx.xx.xx.xxx:12300/saas-cloud-job-service/cloud-job:master-20250315-1f0345a
2025-03-15 17:50:18 The push refers to repository [xxx.xx.xx.xxx:12300/saas-cloud-job-service/cloud-job]
2025-03-15 17:50:18 f392f006c0fa: Preparing
2025-03-15 17:50:18 6639ad0972bc: Preparing
2025-03-15 17:50:18 95aae4bf0704: Preparing
2025-03-15 17:50:18 11cea3feb617: Preparing
2025-03-15 17:50:18 c2798c8f24d6: Preparing
2025-03-15 17:50:18 db2ef8a8a54e: Preparing
2025-03-15 17:50:18 5c7b138ff6a8: Preparing
2025-03-15 17:50:18 fa052c8ec46b: Preparing
2025-03-15 17:50:18 3ddd373c9e01: Preparing
2025-03-15 17:50:18 3c8879ab2cf2: Preparing
2025-03-15 17:50:18 db2ef8a8a54e: Waiting
2025-03-15 17:50:18 5c7b138ff6a8: Waiting
2025-03-15 17:50:18 fa052c8ec46b: Waiting
2025-03-15 17:50:18 3ddd373c9e01: Waiting
2025-03-15 17:50:18 3c8879ab2cf2: Waiting
2025-03-15 17:50:18 95aae4bf0704: Layer already exists
2025-03-15 17:50:18 6639ad0972bc: Layer already exists
2025-03-15 17:50:18 11cea3feb617: Layer already exists
2025-03-15 17:50:18 c2798c8f24d6: Layer already exists
2025-03-15 17:50:18 fa052c8ec46b: Layer already exists
2025-03-15 17:50:18 3ddd373c9e01: Layer already exists
2025-03-15 17:50:18 db2ef8a8a54e: Layer already exists
2025-03-15 17:50:18 5c7b138ff6a8: Layer already exists
2025-03-15 17:50:18 3c8879ab2cf2: Layer already exists
2025-03-15 17:50:18 f392f006c0fa: Pushed
2025-03-15 17:50:18 master-20250315-1f0345a: digest: sha256:29addda92162e51f606f37749f24d28fe278203db782722995a472c263147fa0 size: 2413
2025-03-15 17:50:18 [Pipeline] echo
2025-03-15 17:50:18 Pushed Docker Image [TAG]: xxx.xx.xx.xxx:12300/saas-cloud-job-service/cloud-job:master-20250315-1f0345a
2025-03-15 17:50:18 [Pipeline] }
2025-03-15 17:50:18 [Pipeline] // withDockerRegistry
2025-03-15 17:50:18 [Pipeline] }
2025-03-15 17:50:18 [Pipeline] // script
2025-03-15 17:50:18 [Pipeline] }
2025-03-15 17:50:18 [Pipeline] // stage
2025-03-15 17:50:18 [Pipeline] stage
2025-03-15 17:50:18 [Pipeline] { (Deploy project)
2025-03-15 17:50:18 [Pipeline] echo
2025-03-15 17:50:18 Publishing project
2025-03-15 17:50:18 [Pipeline] }
2025-03-15 17:50:18 [Pipeline] // stage
2025-03-15 17:50:18 [Pipeline] stage
2025-03-15 17:50:18 [Pipeline] { (Declarative: Post Actions)
2025-03-15 17:50:18 [Pipeline] echo
2025-03-15 17:50:19 This pipeline will always run, begin cleaning workspace.
2025-03-15 17:50:19 [Pipeline] cleanWs
2025-03-15 17:50:19 [WS-CLEANUP] Deleting project workspace...
2025-03-15 17:50:19 [WS-CLEANUP] Deferred wipeout is used...
2025-03-15 17:50:19 [WS-CLEANUP] done
2025-03-15 17:50:19 [Pipeline] echo
2025-03-15 17:50:19 The pipeline succeeded.
2025-03-15 17:50:19 [Pipeline] }
2025-03-15 17:50:19 [Pipeline] // stage
2025-03-15 17:50:19 [Pipeline] }
2025-03-15 17:50:19 [Pipeline] // withEnv
2025-03-15 17:50:19 [Pipeline] }
2025-03-15 17:50:19 [Pipeline] // node
2025-03-15 17:50:19 [Pipeline] End of Pipeline
2025-03-15 17:50:19 Finished: SUCCESS
日志 第9行: Stage : (Pull code) 拉取代码 ,检出分支
日志 第37行: [Pipeline] { (Build project) 构建项目
日志 第101行: [Pipeline] { (Push Docker image) 开始推送镜像
日志 第153行: [Pipeline] { (Deploy project) 开始发布部署 ,这里Pipeline 没有写任何东西,因为后面我们会把Image 发布到 K8S 上。
日志 第159行: [Pipeline] { (Declarative: Post Actions) 构建后的处理工作,清理工作空间等
日志 第174行: [Pipeline] End of Pipeline , 完成了整个构建
这就是一个完整的构建流程,当然还有一些细节 优化,比如错误重试,任务超时时间等一些功能。
总结
本来从零到一使用Jenkins 如何构建项目,熟悉整个Pipeline 流程 。