jenkins&&docker安装
核心点是3个主要挂载的,socker.sock需要根据情况定,需要以root身份运行
version: '3'
services:
jenkins:
image: harbor.iovhm.com/hub/jenkins/jenkins:2.488-jdk17
container_name: jenkins
restart: always
privileged: true
user: root
ports:
- "8080:8080"
volumes:
- ./jenkins_home:/var/jenkins_home
- ./m2:/root/.m2
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
environment:
- TZ=Asia/Shanghai
准备工作
需要先建立拉取代码和推送docker镜像使用的用户名密码凭据
系统管理 > 凭据管理 > 全局 > Add Credentials
新建pipeline (流水线项目)
然后根据项目类型,将后面章节的pipeline脚本复制到项目配置
springboot 多项目
当项目有多个子项目时,一个一个建确实比较麻烦,可以使用如下代码示例
特别注意:sh代码或者代码块,当使用三个单引号(''')时候,无法传入局部变量,需要换成三个双引号("""),使用双引号的时候需要对sh代码块特殊字符进行转义
- 既三个单引号不会对sh代码块的内容处理,其中可以使用的参数只有环境变量参数(通过环境变量中转参数);
- 三个双引号会对sh代码块做字符串替换,所以需要处理特殊字符串,例如原本就需要引用的环境变量符号($)需要修改成(\${var})
// 服务清单:'镜像名:目录路径',新增/删除服务只改这一处
def SERVICES = [
'jfast-auth:jfast-service/jfast-auth',
'jfast-basic:jfast-service/jfast-basic',
'jfast-cloud-docking:jfast-service/jfast-cloud-docking',
'jfast-devops-center:jfast-devops-center',
'jfast-gateway:jfast-gateway',
'jfast-oa-services:jfast-oa-services',
'jfast-research-center:jfast-service/jfast-research-center'
]
pipeline {
agent any
// 环境变量,全局可用
environment {
// GIT仓库地址
GIT_URL = 'https://g.vpclub.cn/park/park-huahai/admin-java.git'
// GIT 仓库凭证
GIT_IDENTITY = 'git-szdev-donglietao'
// 项目名称,将生成docker镜像的名称的一部分
PROJECT_NAME ="gzxfzd"
// docker仓库的分组名称
PROJECT_NS ="vp-park"
// docker仓库地址
DOCKER_REGISTRY ="swr.cn-south-1.myhuaweicloud.com"
// 这三个参数将组合成你的最终docker镜像名称为
// swr.cn-south-1.myhuaweicloud.com/vp-park/gzxfzd/<服务名>
// DOCKER 仓库凭证
DOCKER_IDENTITY = 'docker-huaweicloud'
}
// 构建过程参数
parameters {
// 代码分支
choice(name: 'GIT_BRANCH', choices: ['development', 'release'],description: '代码分支 测试dev,生产release')
// 镜像TAG,将最被添加到docker镜像标签上
// 这个参数将被组合到镜像的最终名称
// swr.cn-south-1.myhuaweicloud.com/vp-park/gzxfzd/<服务名>:test
choice(name:"IMAGE_TAG",choices:["test","prod"],description:"镜像的tag")
// 需要推送的服务
choice(
name: 'PUSH_SERVICE',
choices: (['ALL'] + SERVICES).join('\n'),
description: '需要推送的服务,格式 镜像名:目录路径'
)
// 版本号,留空则自动使用 yyyyMMddHHmm 时间戳
string(name:"VERSION",defaultValue:"",description:"镜像版本号,留空自动生成 yyyyMMddHHmm")
}
tools {
// 这个地方与系统设置的mvn工具包对应
maven "M3"
// JDK版本,与全局jdk工具对应
jdk "JDK-8"
}
stages {
stage('Build') {
steps {
// 注意credentialsId参数,填入你前面创建的git仓库用户名密码
// 注意url参数,填入你的git仓库地址
git branch: "${GIT_BRANCH}", credentialsId: "${GIT_IDENTITY}", url: "${GIT_URL}"
// 构建脚本默认在代码仓库根目录运行
// 如果你的pom.xml文件不在根目录,需要使用dir指令进入到对应的目录
// 或者使用mvn clean compile package -f ./source/pom.xml 指定pom文件位置
// 如果你的pom文件是在源代码的根目录,可以删除dir代码块包裹
dir("./"){
// 注意这里的多行脚本引号
// 如果是三个单引号,则无法引用局部变量
// 如果是三个双引号,可以引用局部变量,但是需要对特殊字符进行转义
sh """
pwd
java -version
mvn clean package -DskipTests
"""
}
}
}
stage("docker"){
steps{
script{
// 使用docker凭据,credentialsId为你前面创建的docker仓库凭据
withCredentials([usernamePassword(credentialsId: "${DOCKER_IDENTITY}", passwordVariable: 'docker_password', usernameVariable: 'docker_username')]) {
def conditionVal= "${PUSH_SERVICE}"
def branch = "${GIT_BRANCH}"
// 版本号:用户输入优先,留空则用 yyyyMMddHHmm 时间戳
def version = "${VERSION}".trim() ? "${VERSION}".trim() : new Date().format('yyyyMMddHHmm')
// 登录一次,后面单服务/全量推送共用
sh """
echo "${docker_password}" | docker login -u "${docker_username}" --password-stdin ${DOCKER_REGISTRY}
"""
if(conditionVal=="ALL"){
for(item in SERVICES){
def serviceName = item.split(':')[0]
def serverPath = item.split(':')[1]
dir("./${serverPath}"){
// 注意这里的多行脚本引号
// 如果是三个单引号,则无法引用局部变量
// 如果是三个双引号,可以引用局部变量,但是需要对特殊字符进行转义
sh """
pwd
echo ${serviceName}
docker build -t ${DOCKER_REGISTRY}/${PROJECT_NS}/${PROJECT_NAME}/${serviceName}:${IMAGE_TAG}-${version} .
docker push ${DOCKER_REGISTRY}/${PROJECT_NS}/${PROJECT_NAME}/${serviceName}:${IMAGE_TAG}-${version}
"""
}
}
}else{
def serviceName = conditionVal.split(':')[0]
def serverPath = conditionVal.split(':')[1]
dir("./${serverPath}"){
// 注意这里的多行脚本引号
// 如果是三个单引号,则无法引用局部变量
// 如果是三个双引号,可以引用局部变量,但是需要对特殊字符进行转义
sh """
pwd
echo ${serviceName}
docker build -t ${DOCKER_REGISTRY}/${PROJECT_NS}/${PROJECT_NAME}/${serviceName}:${IMAGE_TAG}-${version} .
docker push ${DOCKER_REGISTRY}/${PROJECT_NS}/${PROJECT_NAME}/${serviceName}:${IMAGE_TAG}-${version}
"""
}
}
}
}
}
}
}
}
springboot maven Pipeline
pipeline {
agent any
// 环境变量,全局可用
environment {
GIT_URL = 'https://g.vpclub.cn/park/crabapple-drink/crabapple-drink.git'
// GIT 仓库凭证
GIT_IDENTITY = 'git-szdev-donglietao'
// 项目名称,将生成docker镜像的名称的一部分
PROJECT_NAME = 'crabapple-drink'
// docker仓库的分组名称
PROJECT_NS = 'vp-park'
// docker仓库地址
DOCKER_REGISTRY = 'swr.cn-south-1.myhuaweicloud.com'
// 这三个参数将组合成你的最终docker镜像名称为
// swr.cn-south-1.myhuaweicloud.com/vp-park/crabapple-drink
// DOCKER 仓库凭证
DOCKER_IDENTITY = 'docker-huaweicloud'
}
// 构建过程参数
parameters {
// 代码分支
choice(name:"GIT_BRANCH",choices:["development","release"],description:"代码分支")
// 镜像TAG,将最被添加到docker镜像标签上
// 这个参数将被组合到镜像的最终名称
// swr.cn-south-1.myhuaweicloud.com/vp-park/springboot-demo:test
choice(name:"IMAGE_TAG",choices:["test","prod"],description:"镜像的tag")
// 版本号,留空则自动使用 yyyyMMddHHmm 时间戳
string(name:"VERSION",defaultValue:"",description:"镜像版本号,留空自动生成 yyyyMMddHHmm")
}
tools {
// 这个地方与系统设置的mvn工具包对应
maven "M3"
// jdk版本,与全局jdk工具对应
// jdk "JDK-8"
}
stages {
stage('Build') {
steps {
// Get some code from a gitlab
// 注意credentialsId参数,填入你前面创建的git仓库用户名密码
// 注意url参数,填入你的git仓库地址
git branch: "${GIT_BRANCH}", credentialsId: "${GIT_IDENTITY}", url: "${GIT_URL}"
// Run Maven on a Unix agent.
// 构建脚本默认在代码仓库根目录运行
// 如果你的pom.xml文件不在根目录,需要使用dir指令进入到对应的目录
// 或者使用mvn clean compile package -f ./source/pom.xml 指定pom文件位置
// 如果你的pom文件是在源代码的根目录,可以删除dir代码块包裹
dir("./renren-cloud-tenant/"){
sh """
echo \$(pwd)
mvn clean package -DskipTests
"""
}
}
}
stage("docker"){
steps{
// docker build 默认在命令行运行的根目录查找Dockerfile
// 如果你的Dockerfile不在根目录,需要使用dir指令进入到对应的目录
// 如果你的Dockerfile在根目录下,可以删除dir代码块包裹
dir('./renren-cloud-tenant/park-admin/park-admin-server/') {
script{
// 版本号:用户输入优先,留空则用 yyyyMMddHHmm 时间戳
def version = "${VERSION}".trim() ? "${VERSION}".trim() : new Date().format('yyyyMMddHHmm')
// 使用docker凭据,credentialsId为你前面创建的docker仓库凭据
withCredentials([usernamePassword(credentialsId: "${DOCKER_IDENTITY}", passwordVariable: 'docker_password', usernameVariable: 'docker_username')]) {
sh """
echo \$(pwd)
docker login -u ${docker_username} -p ${docker_password} ${DOCKER_REGISTRY}
docker build -t ${DOCKER_REGISTRY}/${PROJECT_NS}/${PROJECT_NAME}:${IMAGE_TAG}-${version} .
docker push ${DOCKER_REGISTRY}/${PROJECT_NS}/${PROJECT_NAME}:${IMAGE_TAG}-${version}
"""
}
}
}
}
}
}
}
点击运行的时候没有出现构造参数界面
在项目配置选项里面,勾选参数化,然后与Pipeline脚本中设置的环境变量对应上。
nodejs Pipeline
pipeline {
agent any
// 环境变量,全局可用
environment {
// GIT仓库地址
GIT_URL = "https://g.vpclub.cn/park/sdyk/front-web-admin.git"
// GIT 仓库凭证
GIT_IDENTITY = "donglietao-vpclub-sz-git"
// 项目名称,将生成docker镜像的名称的一部分
PROJECT_NAME ="nodejs-demo"
// docker仓库的分组名称
PROJECT_NS ="vp-whdev"
// docker仓库地址
DOCKER_REGISTRY ="swr.cn-south-1.myhuaweicloud.com"
// 这三个参数将组合成你的最终docker镜像名称为
// swr.cn-south-1.myhuaweicloud.com/vp-whdev/nodejs-demo
// DOCKER 仓库凭证
DOCKER_IDENTITY = "docker-huaweicloud"
// nodejs专用,nodejs内存溢出错误时候需要
NODE_OPTIONS = "--max-old-space-size=4096"
}
// 构建过程参数
parameters {
// 代码分支
choice(name:"BRANCH",choices:["development","release"],description:"代码分支")
// 镜像TAG,将被添加到docker镜像标签上
choice(name:"IMAGE_TAG",choices:["test","prod"],description:"镜像的tag")
// 这个参数将被组合到镜像的最终名称
// swr.cn-south-1.myhuaweicloud.com/vp-whdev/nodejs-demo:test
// 版本号,留空则自动使用 yyyyMMddHHmm 时间戳
string(name:"VERSION",defaultValue:"",description:"镜像版本号,留空自动生成 yyyyMMddHHmm")
}
stages {
stage('Build') {
steps {
// Get some code from a gitlab
// 注意credentialsId参数,填入你前面创建的git仓库用户名密码
// 注意url参数,填入你的git仓库地址
git branch: "${BRANCH}", credentialsId: "${GIT_IDENTITY}", url: "${GIT_URL}"
// build
// 需要使用的nodejs版本,与全局设置的nodejs工具包名称对应
nodejs('node-18.20') {
sh """
echo \$(pwd)
node -v
npm -v
# 非必须,有时候npm install卡主
# npm cache clean --force
# rm -rf node_modules
# rm package-lock.json
# rm yarn.lock
npm add yarn --registry=https://registry.npmmirror.com
./node_modules/.bin/yarn -v
./node_modules/.bin/yarn install --registry https://registry.npmmirror.com
# 如果不使用yarn
# npm install --registry=https://registry.npmmirror.com
if [ "${IMAGE_TAG}" = "prod" ]; then
./node_modules/.bin/yarn run build:prod
elif [ "${IMAGE_TAG}" = "test" ]; then
./node_modules/.bin/yarn run build:test
else
echo "IMAGE_TAG is neither 'prod' nor 'test'. No build script executed."
fi
"""
}
}
}
stage("docker"){
steps{
script{
// 版本号:用户输入优先,留空则用 yyyyMMddHHmm 时间戳
def version = "${VERSION}".trim() ? "${VERSION}".trim() : new Date().format('yyyyMMddHHmm')
// docker build 默认在命令行运行的根目录查找Dockerfile
// 如果你的Dockerfile不在根目录,需要使用dir指令进入到对应的目录
// 如果你的Dockerfile在根目录下,可以删除dir代码块包裹
withCredentials([usernamePassword(credentialsId: "${DOCKER_IDENTITY}", passwordVariable: 'docker_password', usernameVariable: 'docker_username')]) {
sh """
echo \$(pwd)
docker login -u ${docker_username} -p ${docker_password} ${DOCKER_REGISTRY}
docker build -t ${DOCKER_REGISTRY}/${PROJECT_NS}/${PROJECT_NAME}:${IMAGE_TAG}-${version} .
docker push ${DOCKER_REGISTRY}/${PROJECT_NS}/${PROJECT_NAME}:${IMAGE_TAG}-${version}
"""
}
}
}
}
}
}
nodejs第二种方法,多阶段构建
由于某些依赖需要比较复杂的环境,例如gyp,早期的sass,需要很多依赖,导致整个jenkins环境配置异常复杂,这个时候可以使用docker的多阶段构建
FROM harbor.iovhm.com/hub/node:14.21.3 AS build
WORKDIR /data
COPY ./ /data
RUN cd /data && \
yarn install --registry=https://registry.npmmirror.com && \
yarn run build:prod && \
true
FROM harbor.iovhm.com/hub/nginx:1.14.2
COPY --from=build /data/dist/ /usr/share/nginx/html/management
- 注意第一个构建阶段的AS build,类似与给这个阶段取了个名字
- 注意第二个阶段的 --from=build,可以实现内容共享
相对于第一种方法,则只需要获取代码,打包全部有docker完成




