一次完整的Jenkins部署
具体场景
Jenkins以Docker运行,流水线任务需要部署Spring Boot项目到新的容器中
Jenkins安装
启动
networks:
1panel-network:
external: true
volumes:
jenkins_data:
external: true
services:
jenkins:
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/jenkins/jenkins:lts-jdk17
ports:
- "20071:8080" # Web 访问端口
- "50000:50000" # 添加Agent通信端口
volumes:
- jenkins_data:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
- /usr/libexec/docker/cli-plugins/docker-compose:/usr/libexec/docker/cli-plugins/docker-compose
- /opt/1panel/apps/jenkins/jenkins/tmp:/compose-config/server@tmp # Jenkins流水线执行命令时会有临时路径
- /opt/1panel/apps/server/server:/compose-config/server:rw # Java后端项目目录
networks:
- 1panel-network
restart: on-failure
container_name: jenkins # 固定容器名称,便于维护
user: "1000" # 避免使用root用户(提高安全性)
environment:
- TZ=Asia/Shanghai # 时区设置
security_opt:
- no-new-privileges # 禁止权限提升
group_add:
- "${DOCKER_GID}" # 需获取宿主机docker组的GID
#!/bin/bash
# Jenkins服务管理脚本
COMPOSE_FILE="/opt/1panel/apps/jenkins/jenkins/docker-compose.yaml"
CONTAINER_NAME="jenkins"
# 获取docker组GID
export DOCKER_GID=$(getent group docker | cut -d: -f3)
# 检查是否为root用户
check_root() {
if [ "$(id -u)" != "0" ]; then
echo "请使用root权限运行此脚本"
exit 1
fi
}
# 启动Jenkins
start() {
echo "正在启动Jenkins服务..."
# 创建并授权卷
docker volume create jenkins_data
sudo chown -R 1000:1000 $(docker volume inspect jenkins_data -f '{{.Mountpoint}}')
# 启动服务
docker compose -f $COMPOSE_FILE up -d
if [ $? -eq 0 ]; then
echo "Jenkins服务已成功启动"
else
echo "Jenkins服务启动失败"
exit 1
fi
}
# 停止Jenkins
stop() {
echo "正在停止Jenkins服务..."
docker compose -f $COMPOSE_FILE down
if [ $? -eq 0 ]; then
echo "Jenkins服务已成功停止"
else
echo "Jenkins服务停止失败"
exit 1
fi
}
# 检查Jenkins状态
status() {
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Jenkins服务正在运行"
docker ps --filter name=${CONTAINER_NAME} --format "容器ID: {{.ID}}\n状态: {{.Status}}\n端口: {{.Ports}}"
else
echo "Jenkins服务未运行"
fi
}
# 使用说明
usage() {
echo "使用方法: $0 {start|stop|status}"
echo " start - 启动Jenkins服务"
echo " stop - 停止Jenkins服务"
echo " status - 查看Jenkins服务状态"
exit 1
}
# 主程序
case "$1" in
start)
check_root
start
;;
stop)
check_root
stop
;;
status)
status
;;
*)
usage
;;
esac
exit 0
准备工作
1、启动:略,教程很多;这里我建议先不要下载插件,后面我们配置完镜像源后再下载自己需要的;
2、替换镜像源:清华源
在宿主机执行命令更新文件;PS:如果完全按照我上面的文件运行的Jenkins的情况下
sed -i 's|updates.jenkins.io/download|mirrors.tuna.tsinghua.edu.cn/jenkins|g' /var/lib/docker/volumes/jenkins_data/_data/updates/default.json
sed -i 's|www.google.com|www.baidu.com|g' /var/lib/docker/volumes/jenkins_data/_data/updates/default.json
3、配置Maven(系统管理 --> 全局工具配置 --> Maven 安装)

4、插件:Chinese (Simplified)、Git、DingTalk、Pipeline、Pipeline Utility Steps、Docker API Plugin、Docker Pipeline、Timestamper、Workspace Cleanup Plugin
搭建流水线
我这个搭建就很简单了,总共就两步
第一步:新建任务

第二步:Pipeline脚本,按照注释修改成自己所需要的
pipeline {
agent any
tools {
maven 'apache-maven-3.9.11'
}
environment {
// Docker 镜像信息
APP_NAME = "app"
DOCKER_REGISTRY = "registry.cn-hangzhou.aliyuncs.com"
IMAGE_TAG = "${BUILD_ID}" // 使用构建ID作为镜像标签
// 项目路径配置
COMPOSE_PATH = "/compose-config/server"
DOCKER_COMPOSE_FILE = "${COMPOSE_PATH}/docker-compose.yml"
ENV_FILE = "${COMPOSE_PATH}/.env"
APPLICATION_YML = "${COMPOSE_PATH}/application.yml"
}
stages {
// 阶段 1: 代码检出
stage('Checkout') {
steps {
script {
// 先获取代码
git branch: 'DEV_BASE', // 你的分支
url: '', // 你的代码地址
credentialsId: '' // 你的Jenkins凭证ID
// 获取最新commit message
env.COMMIT_MESSAGE = sh(
script: 'git log -1 --pretty=format:"%s"',
returnStdout: true
).trim()
echo "✅ 获取到提交信息: ${env.COMMIT_MESSAGE}"
}
}
}
// 阶段 2: Maven 构建
stage('Maven Build') {
steps {
script {
// 确定目标jar包的实际路径
env.JAR_PATH = sh(
script: 'find . -name app.jar -print -quit', // 这里记得替换成你的项目构建完成后的jar包名
returnStdout: true
).trim()
if (!env.JAR_PATH) {
error "❌ 找不到 app.jar 文件"
}
echo "✅ 找到jar包位置: ${env.JAR_PATH}"
}
sh 'mvn clean package -DskipTests'
}
}
// 阶段 3: 构建 Docker 镜像
stage('Build Image') {
steps {
script {
// 登录阿里云容器镜像服务
withCredentials([usernamePassword(
credentialsId: 'aliyun-docker-creds',
usernameVariable: 'REG_USER',
passwordVariable: 'REG_PASSWORD'
)]) {
sh """
echo ${REG_PASSWORD} | docker login -u ${REG_USER} --password-stdin registry.cn-hangzhou.aliyuncs.com
"""
}
// 上面这一步是因为我的Dockerfile里面采用私有镜像文件,不需要可以不要
// 使用动态确定的jar路径
sh """
docker build \
-t ${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG} \
--build-arg JAR_PATH=${env.JAR_PATH} \
.
"""
}
}
}
// 阶段 4: 更新 docker-compose 配置
stage('Update Config') {
steps {
script {
// 更新 .env 文件中的镜像标签
sh '''
sed -i -r "s|IMAGE=.*|IMAGE=${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}|g" ${ENV_FILE}
'''
}
}
}
// 阶段 5: Docker Compose 部署
stage('Deploy') {
steps {
script {
// 切换到 docker-compose 目录
dir(COMPOSE_PATH) {
// 删除旧容器 (保留数据卷)
sh 'docker compose down'
// 使用 docker-compose 启动服务
sh 'docker compose up -d'
// 清理旧镜像 (保留最近3次构建)
sh '''
CURRENT_IMAGE=${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}
docker images --format "{{.Repository}}:{{.Tag}}" \
| grep "${DOCKER_REGISTRY}/${APP_NAME}" \
| grep -v "${IMAGE_TAG}" \
| sort -Vr | tail -n +4 \
| xargs -r docker rmi 2>/dev/null || true
'''
}
}
}
}
}
post {
always {
script {
// 清理 Docker 登录凭证
sh 'docker logout registry.cn-hangzhou.aliyuncs.com || true'
}
}
success {
echo "✅ ${APP_NAME} 部署成功! 镜像版本: ${IMAGE_TAG}"
}
failure {
script {
// 安全获取提交信息
def commitMsg = env.COMMIT_MESSAGE ?: "无法获取提交信息"
// 使用钉钉机器人ID发送通知
dingtalk (
robot: '', // 这里是之前安装的钉钉的消息推送配置的机器人ID,不需要这一整块都可以删除
type: 'ACTION_CARD',
title: "❌ ${APP_NAME} 构建失败通知",
text: [
"# 🔔 Jenkins构建失败通知",
"",
"### 📋 构建信息",
"---",
"- 🏷️ **应用名称**:`${APP_NAME}`",
"- 🔨 **构建编号**:`#${BUILD_NUMBER}`",
"- 📦 **镜像标签**:`${IMAGE_TAG}`",
"- 📝 **提交信息**:`${commitMsg}`",
"",
"### 🔍 快速操作",
"---",
"点击下方按钮查看详细信息"
],
btnLayout: 'H',
btns: [
[title: '📄 查看构建日志', actionUrl: "${env.BUILD_URL}console"],
[title: '🏠 返回Jenkins首页', actionUrl: "${env.JENKINS_URL}"]
]
)
// 控制台输出
echo "❌ ${APP_NAME} 部署失败!"
echo "提交信息: ${commitMsg}"
}
}
}
}
第三步:其他都不用操作,直接保存就行

浙公网安备 33010602011771号