20 分钟搞定:Jenkins + Docker 一键流水线,自动构建镜像并部署到远程服务器
Jenkins 后端服务流水线部署脚本
节点设置
此处配置的节点是用来执行脚本中的每一个步骤(stage)的,包括但不限于代码构建、镜像构建/推送等
agent any
agent { label 'master' }
-
可通过 agent 设置流水线使用到节点
-
any 表示任意节点
-
{ label 'master' } 表示标签为 master 到节点
-
-
此处可使用的节点可在节点和云管理查看。查看路径:右上角齿轮图标“系统设置” --> 节点和云管理 --> 节点列表
-
master 节点是内置节点,默认没有标签,可在 master 节点详情内 --> 配置从节点设置标签
-
备注:设置节点标签时注意大小写、空格。
环境变量设置
此处配置的环境变量可在整个脚本内使用,将动态的变量设置在此处可形成通用脚本,需要复制流水线时修改此处的变量即可
environment {
// Git 仓库配置
GIT_URL = 'git@git.xxx.com:xxx.git'// 替换为你的代码仓库
GIT_KEY_ACR_CRED = 'git-ssh-key'
// Docker 镜像相关配置
DOCKER_IMAGE_REGISTRY = 'registry.xxx.aliyuncs.com'// 替换为你的镜像仓库
DOCKER_IMAGE_ACR_CRED = 'docker-cred'
IMAGE_PRE_NAME = 'xxxx'// 镜像名称前缀
IMAGE_NAME = 'xxx-service'// 替换为你的应用名称
// 远程服务器
REMOTE_HOST = 'xxx.xxx.xxx.xx'// 服务器 IP
REMOTE_HOST_ACR_CRED = 'host-cred'
}
-
GIT_URL 代码仓库:存储代码的仓库,用来获取代码至 jenkins
-
GIT_KEY_ACR_CRED:访问代码仓库的凭据
-
DOCKER_IMAGE_REGISTRY 镜像仓库:存储 docker 镜像的仓库,可拉取/推送镜像
-
DOCKER_IMAGE_ACR_CRED:用来访问镜像仓库的凭据
-
IMAGE_PRE_NAME:镜像名称前缀
-
IMAGE_NAME:应用名称,用来拼接镜像名称
-
REMOTE_HOST 远程服务器 IP:我们需要运行服务的服务器 IP
-
REMOTE_HOST_ACR_CRED:用来访问远程服务器的凭据
-
DOCKER_IMAGE_ACR_CRED、DOCKER_IMAGE_ACR_CRED、REMOTE_HOST_ACR_CRED 需要去凭据管理添加
-
添加路径:右上角齿轮图标“系统设置” --> 凭据管理 --> 在界面上找到域选一个点进去
-
点击右上角Add Credentials添加
-
类型可选择username with password、SSH username with private key
- 其中的 ID 就是我们需要的值
,可根据喜好设置,不填写会自动生成
-
构建工具设置
这里设置构建代码的 Maven 工具
tools {
// Install the Maven version configured as "M3" and add it to the path.
maven "Maven3"
}
-
这里设置的工具需要在全局工具配置添加
-
添加路径:右上角齿轮图标“系统设置” --> 全局工具配置
-
找到Maven 配置,这里可用设置 maven 本地仓库、settings.xml 文件
-
找到Maven 安装,安装 Maven 时注意 Name,这里填写的信息就是脚本中使用的
-
安装 Maven 时可选择自动安装,可选版本。建议版本与开发保持一致
代码检出
拉取仓库中的代码
此操作属于运行在节点的步骤,需要添加在 stages 对象中
stage('Checkout') {
steps {
// Get some code from a GitHub repository
git branch: 'master',
url: GIT_URL,
credentialsId: GIT_KEY_ACR_CRED
}
}
-
git branch: 'master':用于拉取的分支
-
url: GIT_URL
-
设置代码仓库地址,可以使用环境变量中的值,也可直接填写代码仓库字符串'git@git.xxx.com:xxx.git'
-
-
credentialsId:用于设置仓库访问凭据
工程构建
使用 Maven 构建 Maven 工程中的 Java 代码
此操作属于运行在节点的步骤,需要添加在 stages 对象中
stage('Build') {
steps {
// Run Maven on a Unix agent.
sh "mvn -Dmaven.test.failure.ignore=true clean package"
// To run Maven on a Windows agent, use
// bat "mvn -Dmaven.test.failure.ignore=true clean package"
}
post {
// If Maven was able to run the tests, record the test results and archive the jar file.
success {
archiveArtifacts 'target/*.jar'
}
}
}
-
sh "mvn -Dmaven.test.failure.ignore=true clean package"
-
先清理上次构建的产物,然后重新打包
-
-
post 是后置处理器
-
success 当这个步骤运行成功后所做的操作
-
此处所做的操作是归档,可在流水线每次的运行记录内Build Artifacts位置找到
-
构建、推送 Dokcer 镜像
此操作属于运行在节点的步骤,需要添加在 stages 对象中
stage('Build and Push Docker Image') {
steps {
script {
// 生成时间戳
def timestamp = new Date().format('yyyyMMddHHmm', TimeZone.getTimeZone('Asia/Shanghai'))
def imageTag = "${IMAGE_NAME}:${timestamp}"
def fullImageNameWithTimestamp = "${DOCKER_IMAGE_REGISTRY}/${IMAGE_PRE_NAME}/${imageTag}"
// 使用宿主机 Docker 构建镜像
echo "Building Docker image: ${fullImageNameWithTimestamp}"
sh "docker build -t ${fullImageNameWithTimestamp} ."
withCredentials([usernamePassword(credentialsId: DOCKER_IMAGE_ACR_CRED, usernameVariable:'REG_USER', passwordVariable:'REG_PASS')]) {
// 登录到镜像仓库
echo "Login Docker..."
sh "docker login --username \$REG_USER -p \$REG_PASS \$DOCKER_IMAGE_REGISTRY"
// 推送镜像
echo "Push Docker Image ${fullImageNameWithTimestamp}"
sh "docker push ${fullImageNameWithTimestamp}"
}
// 输出构建信息
echo "Successfully built and pushed image: ${fullImageNameWithTimestamp}"
// 将镜像名称保存到环境变量,供后续步骤使用
env.BUILT_IMAGE = fullImageNameWithTimestamp
}
}
}
-
此处使用当前时间为镜像设置 tag
-
镜像名称格式:<镜像仓库地址>/<镜像名称前缀>/<应用名称>:<当前时间>
-
sh "docker build -t ${fullImageNameWithTimestamp} ."
-
使用 docker 构建镜像
-
-
withCredentials 使用凭据登陆、推送镜像
-
登陆仓库: sh "docker login --username $REG_USER -p $REG_PASS $DOCKER_IMAGE_REGISTRY"
-
推送镜像:sh "docker push ${fullImageNameWithTimestamp}"
-
将镜像名称保存到环境变量,供后续步骤使用:env.BUILT_IMAGE = fullImageNameWithTimestamp
-
部署到远程服务器
此操作属于运行在节点的步骤,需要添加在 stages 对象中
stage('Deploy to Remote Host') {
steps {
withCredentials([usernamePassword(credentialsId: REMOTE_HOST_ACR_CRED, usernameVariable: 'REMOTE_USER', passwordVariable: 'REMOTE_PWD')]) {
sh """
sshpass -p \$REMOTE_PWD ssh -T -o StrictHostKeyChecking=no \
\$REMOTE_USER@${REMOTE_HOST} << 'EOF'
# 去往工作目录
cd /app/${IMAGE_NAME}
# 修改 .env 文件
sed -i '/${IMAGE_NAME}/c\\SERVICE_V=${BUILT_IMAGE}' .env
# 停止目标服务
docker-compose stop ${IMAGE_NAME}
# 删除目标容器
docker-compose rm -f ${IMAGE_NAME}
# 启动目标容器
docker-compose up -d ${IMAGE_NAME}
EOF
"""
}
}
}
-
withCredentials:使用凭据连接远程服务器
-
此处使用 sshpass 连接到远程服务器,这里部署 Jenkins 的容器/服务器中需要提前安装 sshpass
-
此处 << 'EOF' ... EOF 不能缺失,末尾的EOF需要独占一行且前方不得有任何字符字符
-
cd /app/${IMAGE_NAME}
-
定位至远程服务器的工作目录
-
-
sed -i '/${IMAGE_NAME}/c\SERVICE_V=${BUILT_IMAGE}' .env
-
修改 docker-compose 的配置文件,将 docker-compose 启动使用的镜像修改为前述步骤推送至仓库的镜像
-
-
停止服务:docker-compose stop ${IMAGE_NAME}
-
删除目标容器:docker-compose rm -f ${IMAGE_NAME}
-
启动目标容器:docker-compose up -d ${IMAGE_NAME}
脚本源码
pipeline {
agent { label 'master' }
environment {
// Git 仓库配置
GIT_URL = 'git@git.xxx.com:xxx.git'// 替换为你的代码仓库
GIT_KEY_ACR_CRED = 'git-ssh-key'
// Docker 镜像相关配置
DOCKER_IMAGE_REGISTRY = 'registry.xxx.aliyuncs.com'// 替换为你的镜像仓库
DOCKER_IMAGE_ACR_CRED = 'docker-cred'
IMAGE_PRE_NAME = 'xxxx'// 镜像名称前缀
IMAGE_NAME = 'xxx-service'// 替换为你的应用名称
// 远程服务器
REMOTE_HOST = 'xxx.xxx.xxx.xx'// 服务器 IP
REMOTE_HOST_ACR_CRED = 'host-cred'
}
tools {
// Install the Maven version configured as "M3" and add it to the path.
maven "Maven3"
}
stages {
stage('Checkout') {
steps {
// Get some code from a GitHub repository
git branch:'master',
url: GIT_URL,
credentialsId: GIT_KEY_ACR_CRED
}
}
stage('Build') {
steps {
// Run Maven on a Unix agent.
sh "mvn -Dmaven.test.failure.ignore=true clean package"
// To run Maven on a Windows agent, use
// bat "mvn -Dmaven.test.failure.ignore=true clean package"
}
post {
// If Maven was able to run the tests, record the test results and archive the jar file.
success {
archiveArtifacts 'target/*.jar'
}
}
}
stage('Build and Push Docker Image') {
steps {
script {
// 生成时间戳
def timestamp = new Date().format('yyyyMMddHHmm', TimeZone.getTimeZone('Asia/Shanghai'))
def imageTag = "${IMAGE_NAME}:${timestamp}"
def fullImageNameWithTimestamp = "${DOCKER_IMAGE_REGISTRY}/${IMAGE_PRE_NAME}/${imageTag}"
// 使用宿主机 Docker 构建镜像
echo "Building Docker image: ${fullImageNameWithTimestamp}"
sh "docker build -t ${fullImageNameWithTimestamp} ."
withCredentials([usernamePassword(credentialsId: DOCKER_IMAGE_ACR_CRED, usernameVariable:'REG_USER', passwordVariable:'REG_PASS')]) {
// 登录到镜像仓库
echo "Login Docker..."
sh "docker login --username \$REG_USER -p \$REG_PASS \$DOCKER_IMAGE_REGISTRY"
// 推送镜像
echo "Push Docker Image ${fullImageNameWithTimestamp}"
sh "docker push ${fullImageNameWithTimestamp}"
}
// 输出构建信息
echo "Successfully built and pushed image: ${fullImageNameWithTimestamp}"
// 将镜像名称保存到环境变量,供后续步骤使用
env.BUILT_IMAGE = fullImageNameWithTimestamp
}
}
}
stage('Deploy to Remote Host') {
steps {
withCredentials([usernamePassword(credentialsId: REMOTE_HOST_ACR_CRED, usernameVariable:'REMOTE_USER', passwordVariable:'REMOTE_PWD')]) {
sh """
sshpass -p \$REMOTE_PWD ssh -T -o StrictHostKeyChecking=no \
\$REMOTE_USER@${REMOTE_HOST} << 'EOF'
# 去往工作目录
cd /app/${IMAGE_NAME}
# 修改 .env 文件
sed -i '/${IMAGE_NAME}/c\\SERVICE_V=${BUILT_IMAGE}' .env
# 停止目标服务
docker-compose stop ${IMAGE_NAME}
# 删除目标容器
docker-compose rm -f ${IMAGE_NAME}
# 启动目标容器
docker-compose up -d ${IMAGE_NAME}
EOF
"""
}
}
}
}
}更多推荐


所有评论(0)