1. 项目概述为什么今天还在认真搭建 Jenkins你点开这篇内容大概率不是因为对 Jenkins 有情怀而是被现实按在地上摩擦过——改完一行代码手动打包、传服务器、解压、重启 Tomcat等三分钟看日志报错前端同事改个按钮颜色要等后端发版窗口测试环境三天没更新bug 复现不了上线前一小时发现配置漏了手抖输错命令直接把生产库连错了……这些不是段子是我在 2018 年接手第一个微服务项目时的真实夜班记录。Jenkins 确实“老”但它的不可替代性恰恰藏在“不性感”里它不靠 UI 吸睛不靠云原生概念讲故事而是用最笨的办法——把人干的重复动作变成可追溯、可回滚、可审计、可交接的标准化流水线。尤其当你的团队开始出现“有人离职部署脚本就失联”“新同事配环境花两天还配不对”“每次上线都要拉群喊人盯屏”这类信号时Jenkins 就不是“要不要上”的问题而是“再不上系统稳定性已经由运气决定”的临界点。更关键的是Jenkins Docker 的组合正在成为中小团队技术基建的“事实标准”。你看热搜词里反复出现的“docker部署springboot项目”“前端vue项目部署”“jenkins自动部署”背后全是同一套逻辑用 Docker 镜像固化运行时环境Java 版本、Node.js 版本、Python 依赖、Nginx 配置用 Jenkins Pipeline 脚本固化构建部署流程拉代码→装依赖→跑单元测试→打镜像→推仓库→启容器。它不追求 Kubernetes 那种抽象层级而是让每个步骤都看得见、改得了、查得清。我带过的 7 个不同行业项目从政务系统到跨境电商 SaaS最终落地的自动化方案90% 都是从 Jenkins Docker 起步再逐步演进。所以这篇内容不讲“Jenkins 是什么”而是直接带你走通一条真实生产环境可用的路径从一台干净的 Ubuntu 服务器开始安装 Jenkins、集成 Docker、配置权限、编写可复用的 Pipeline 脚本、处理 Java/Python/前端项目的差异化部署、解决镜像体积大、构建慢、权限报错等高频坑。所有操作基于 2024 年最新 LTS 版本Jenkins 2.440.4 Docker 24.0.7所有命令可复制粘贴所有配置项都解释清楚“为什么这么设”。如果你刚配好 Jenkins 却卡在“构建时报 Permission denied”、或者写完 Pipeline 却发现“镜像推不到私有仓库”那接下来的内容就是为你写的。2. 环境准备与核心架构设计2.1 为什么必须用 Docker 运行 Jenkins很多人第一步就栽在安装方式上直接apt install jenkins然后在宿主机上跑。这看似简单但埋下三个致命隐患环境污染Jenkins 插件会往系统/var/lib/jenkins写大量缓存和插件包升级 Jenkins 时极易和系统 Java 版本冲突权限地狱Jenkins 进程默认以jenkins用户运行而 Docker 守护进程需要docker组权限硬加用户到docker组会导致安全策略失效比如 CI 任务能随意删宿主机容器扩展性归零未来想加一个 SonarQube 代码扫描节点得在宿主机再装一套 Java 环境版本还不能和 Jenkins 冲突。正确姿势是用 Docker 容器运行 Jenkins 主体再通过 Docker Socket 挂载让 Jenkins 调用宿主机 Docker 引擎。这本质是“容器化运维工具”好处立竿见影Jenkins 升级 docker pull jenkins/jenkins:ltsdocker-compose up -d5 秒完成旧数据全在挂载卷里权限隔离清晰Jenkins 容器只拥有它该有的权限通过--group-add docker显式授权不会越界操作宿主机扩展即加容器SonarQube、Nexus 私有仓库、GitLab Runner全用docker-compose.yml一键编排。提示不要用docker run -d --name jenkins -p 8080:8080 -v /var/run/docker.sock:/var/run/docker.sock jenkins/jenkins:lts这种裸命令。必须用docker-compose.yml管理否则后续加挂载卷、环境变量、健康检查都会失控。2.2 最小可行架构图非理论是实操拓扑我们不画虚的“CI/CD 分层架构图”直接给你生产环境里真正连着线的设备关系组件部署位置关键作用我的实际配置Jenkins Master一台 4C8G Ubuntu 22.04 云服务器接收 Git Webhook、调度任务、展示构建日志容器名jenkins-master挂载/data/jenkins:/var/jenkins_homeDocker Engine同一台服务器Jenkins 宿主机构建镜像、运行测试容器、部署应用容器Docker 24.0.7启用--experimental为 BuildKit 做准备Private Registry同一台服务器用registry:2容器存储项目镜像避免推 Docker Hub 的网络延迟和速率限制docker run -d -p 5000:5000 -v /data/registry:/var/lib/registry registry:2Git 仓库自建 GitLab 或 GitHub 私有仓库代码源触发 Jenkins 构建必须配置 WebhookURL 为http://服务器IP:8080/project/项目名这个架构的关键在于所有组件都在同一台物理机或同一 VPC 内网。为什么因为 Jenkins 构建时要频繁读写 Docker 镜像层动辄几百 MB跨机器传输会把构建时间从 2 分钟拖到 15 分钟。我试过把 Registry 放在阿里云 ACR结果 SpringBoot 项目构建阶段光 push 镜像就卡 8 分钟最后还是搬回本地 Registry。2.3 操作系统与基础依赖确认别跳过这一步很多“安装失败”其实源于系统预设。在 Ubuntu 22.04 上执行# 1. 确认内核支持 overlay2Docker 默认存储驱动 $ uname -r 5.15.0-101-generic # ✅ 5.15 内核原生支持 # 2. 检查 systemd 是否启用 cgroup v2Docker 24 强制要求 $ cat /proc/1/cgroup | head -1 0::/ # ✅ 如果显示 0::/ 表示 cgroup v2 已启用若显示 1:namesystemd:/... 则需修改 grub # 3. 禁用 swapDocker 官方明确要求否则启动容器报错 $ sudo swapoff -a $ echo # swap disabled for docker | sudo tee -a /etc/fstab注意如果cat /proc/1/cgroup显示的是1:namesystemd:/说明系统在用 cgroup v1。必须修改/etc/default/grub将GRUB_CMDLINE_LINUX改为GRUB_CMDLINE_LINUXsystemd.unified_cgroup_hierarchy1然后sudo update-grub sudo reboot。这是 Docker 24 的硬性门槛跳过必踩坑。2.4 Docker 安装与 Jenkins 容器初始化严格按官方文档来不用snap或apt仓库存疑版本# 卸载旧版如有 sudo apt-get remove docker docker-engine docker.io containerd runc # 安装依赖 sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg lsb-release # 添加 Docker 官方 GPG 密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 添加稳定版仓库 echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装 Docker Engine sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # 启动并设开机自启 sudo systemctl enable docker sudo systemctl start docker # 验证必须看到 Hello from Docker! sudo docker run hello-world现在创建docker-compose.yml# /data/jenkins/docker-compose.yml version: 3.8 services: jenkins-master: image: jenkins/jenkins:lts-jdk17 container_name: jenkins-master restart: unless-stopped ports: - 8080:8080 - 50000:50000 # JNLP agent 端口后续加 slave 节点用 environment: - JAVA_OPTS-Djenkins.install.runSetupWizardfalse -Dhudson.model.DownloadService.noSignatureChecktrue - JENKINS_OPTS--httpKeepAliveTimeout60000 volumes: - /data/jenkins:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock:ro # 只读挂载安全第一 - /usr/bin/docker:/usr/bin/docker:ro # 让容器内能调用宿主机 docker CLI - /data/registry:/data/registry:ro # 本地 Registry 挂载供 Jenkins 推送 group_add: - docker # 关键让 jenkins 用户加入 docker 组 networks: - jenkins-net networks: jenkins-net: driver: bridge启动cd /data/jenkins sudo docker-compose up -d实操心得第一次启动后sudo docker logs jenkins-master查看日志重点找Jenkins initial setup is required后面的 12 位管理员密码。这个密码在/data/jenkins/secrets/initialAdminPassword文件里但直接读文件不如看日志快。另外JAVA_OPTS中的-Djenkins.install.runSetupWizardfalse是为了跳过向导避免 Jenkins 自动装一堆用不到的插件如 Blue Ocean我们后面按需装。3. Jenkins 核心配置与权限体系搭建3.1 初始化配置绕过向导直击生产级设置访问http://服务器IP:8080输入初始密码后立刻选择 “Install suggested plugins” → 点 “Restart Jenkins”。不要选 “Select plugins to install”因为建议插件集24 个已覆盖 95% 场景Git、Docker Pipeline、Pipeline Utility Steps、Role-based Authorization Strategy权限控制、Email Extension邮件通知。重启后登录管理员账号进入Manage Jenkins → Configure SystemJenkins URL填http://服务器IP:8080必须带协议和端口否则邮件通知链接会错Global properties → Environment variables添加DOCKER_REGISTRYhttp://服务器IP:5000后续 Pipeline 脚本直接引用E-mail NotificationSMTP 配置以腾讯企业邮箱为例SMTP serversmtp.exmail.qq.comDefault user E-mail suffixyourcompany.comTest e-mail填自己邮箱点 “Test configuration” 验证。注意这里不配置 “JDK” 或 “Maven” 全局工具。因为我们要用 Docker 容器提供构建环境Java 17、Maven 3.9、Node 18全局工具反而会造成版本混乱。所有构建环境都在 Pipeline 里声明。3.2 权限模型为什么 Role-based Strategy 是唯一选择Jenkins 默认的 “Logged-in users can do anything” 权限模型在 3 人以上团队就是灾难。曾有个客户测试人员误点了 “Delete this job”整个支付系统的部署流水线没了。我们必须用Role-based Authorization Strategy插件已随建议插件安装。进入Manage Jenkins → Manage and Assign RolesManage Roles创建三类角色admin-role勾选Overall/Read,Overall/Administer,Job/Build,Job/Cancel,Job/Configure,Job/Delete,Job/Read,Job/Workspace,SCM/Tag,View/Read,View/Configuredev-role勾选Job/Build,Job/Cancel,Job/Read,SCM/Tag,View/Readtest-role勾选Job/Build,Job/Read,View/ReadAssign Roles将管理员账号分配给admin-role开发人员账号分配给dev-role测试人员账号分配给test-role。关键细节SCM/Tag权限允许开发人员在构建成功后自动打 Git Tag如v1.2.3这是发布管理的基础。没有这个权限每次发版都要运维手动打 Tag效率归零。3.3 凭据管理安全存储敏感信息的唯一方式所有密码、Token、密钥绝不能写在 Pipeline 脚本里。必须用 Jenkins 内置凭据系统进入Credentials → System → Global credentials → Add CredentialsKind选Username with passwordScope选Global (Jenkins, nodes, items, all child items)Username填 Git 仓库用户名如gitlab-ciPassword填对应 TokenGitLab 生成 Personal Access Token勾选read_repository和write_repositoryID填gitlab-credentials后续 Pipeline 用这个 ID 引用。同样方式添加 Docker Registry 凭据KindUsername with passwordUsernameadmin本地 Registry 默认用户名PasswordHarbor12345启动 Registry 时指定的密码IDdocker-registry-credentials。实操心得凭据 ID 必须全小写、无下划线、无特殊字符。我见过因 ID 写成docker_registry_creds导致 Pipeline 报No credentials matching docker_registry_creds found的案例。Jenkins 凭据系统对 ID 匹配极其严格。3.4 全局工具配置只配 Docker其他交给容器进入Manage Jenkins → Global Tool ConfigurationDocker点击 “Docker” → “Docker installation” → 勾选 “Install automatically” → 选择 “Docker 24.0.7” → “Install from docker.com”其他工具JDK/Maven/Node全部留空。为什么因为 Jenkins 本身只负责调度真正的构建环境由 Docker 容器提供。比如 Maven 构建我们用maven:3.9-amazoncorretto-17镜像里面已预装 JDK 17 和 Maven 3.9版本精准可控。如果在这里配了全局 MavenPipeline 里又用容器两个环境版本不一致构建结果就不可信。4. Pipeline 脚本编写与多语言项目部署实战4.1 Pipeline 基础语法Declarative vs Scripted选哪个Jenkins Pipeline 有两种写法Declarative Pipeline结构固定pipeline { agent {} stages {} }语法严格适合新手和标准化场景Scripted Pipeline基于 Groovy灵活度高但易出错适合复杂逻辑。强烈推荐 Declarative。原因很实在错误提示友好stage(Build)缺少steps{}Jenkins 直接标红报错行IDE 支持好VS Code 安装 “Jenkins Pipeline Linter Connector” 插件写完就能校验语法可视化强Blue Ocean 界面能自动生成流程图每个 stage 点开看详细日志。下面所有示例均用 Declarative。4.2 SpringBoot 项目部署从代码到容器的完整链路假设你的项目结构是标准 Mavenmy-springboot-app/ ├── pom.xml ├── src/ │ └── main/ │ ├── java/ │ └── resources/ └── Jenkinsfile # 放在项目根目录Jenkinsfile内容pipeline { agent { docker { image maven:3.9-amazoncorretto-17 args -u root // 以 root 运行避免权限问题 reuseNode true // 复用 Jenkins agent 节点共享工作区 } } environment { // 从 Jenkins 全局配置读取 DOCKER_REGISTRY http://服务器IP:5000 APP_NAME my-springboot-app IMAGE_TAG ${BUILD_NUMBER} // 用构建号做镜像 tag } stages { stage(Checkout) { steps { checkout scm // 从 Git 拉代码 } } stage(Build) { steps { sh mvn clean package -DskipTests // 跳过测试加快构建 sh cp target/*.jar app.jar // 复制 jar 到工作区根目录方便后续 Dockerfile 引用 } } stage(Build Docker Image) { steps { script { // 构建镜像tag 为 registry 地址 项目名 构建号 def customImage docker.build(${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}) // 推送到本地 Registry docker.withRegistry(${DOCKER_REGISTRY}, docker-registry-credentials) { customImage.push() } } } } stage(Deploy) { steps { script { // 在宿主机执行停止旧容器启动新容器 sh docker stop ${APP_NAME} || true docker rm ${APP_NAME} || true docker run -d \ --name ${APP_NAME} \ -p 8081:8080 \ -e SPRING_PROFILES_ACTIVEprod \ --restartalways \ ${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG} } } } } post { success { emailext ( subject: SUCCESS: ${env.JOB_NAME} [${env.BUILD_NUMBER}], body: p构建成功/p p项目${env.JOB_NAME}/p p构建号${env.BUILD_NUMBER}/p p镜像地址a href${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}/a/p, recipientProviders: [[$class: DevelopersRecipientProvider]] ) } failure { emailext ( subject: FAILED: ${env.JOB_NAME} [${env.BUILD_NUMBER}], body: p构建失败请检查日志。/p p构建日志a href${env.BUILD_URL}console${env.BUILD_URL}console/a/p, recipientProviders: [[$class: DevelopersRecipientProvider]] ) } } }关键参数解析reuseNode true让 Docker 容器和 Jenkins agent 共享同一个工作区/var/jenkins_home/workspace/job-name否则mvn package生成的 jar 在容器里docker build在宿主机找不到args -u rootMaven 镜像默认用户是root但 Jenkins 启动容器时会切到jenkins用户导致mvn命令权限不足强制-u root解决docker.withRegistry(...)用之前配置的凭据 IDdocker-registry-credentials认证否则 push 会 401 Unauthorized。4.3 Python Flask 项目部署处理虚拟环境与依赖Flask 项目结构my-flask-app/ ├── requirements.txt ├── app.py ├── Dockerfile └── JenkinsfileDockerfileFROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD [gunicorn, --bind, 0.0.0.0:5000, app:app]Jenkinsfilepipeline { agent any // 不用 Docker agent因为要先构建镜像再推送到 Registry environment { DOCKER_REGISTRY http://服务器IP:5000 APP_NAME my-flask-app IMAGE_TAG ${BUILD_NUMBER} } stages { stage(Checkout) { steps { checkout scm } } stage(Build and Push Docker Image) { steps { script { // 构建镜像使用项目根目录的 Dockerfile def customImage docker.build(${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}) // 推送 docker.withRegistry(${DOCKER_REGISTRY}, docker-registry-credentials) { customImage.push() } } } } stage(Deploy) { steps { script { sh docker stop ${APP_NAME} || true docker rm ${APP_NAME} || true docker run -d \ --name ${APP_NAME} \ -p 5000:5000 \ --restartalways \ ${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG} } } } } post { success { emailext ( subject: SUCCESS: ${env.JOB_NAME} [${env.BUILD_NUMBER}], body: Flask 应用部署成功访问 http://服务器IP:5000, recipientProviders: [[$class: DevelopersRecipientProvider]] ) } } }注意Python 项目不用在 Pipeline 里装依赖全部交给Dockerfile的RUN pip install。这样做的好处是依赖版本锁定在镜像层和 Jenkins 构建环境无关pip install的缓存可以复用Docker 构建时requirements.txt不变则跳过安装避免 Jenkins 服务器上 Python 环境混乱比如全局 pip 和 virtualenv 冲突。4.4 前端 Vue 项目部署Nginx 静态资源托管Vue 项目结构my-vue-app/ ├── package.json ├── vue.config.js ├── nginx.conf # 自定义 Nginx 配置 └── Jenkinsfilenginx.confserver { listen 80; location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://backend-service:8080/; } }Jenkinsfilepipeline { agent { docker { image node:18-alpine args -u root reuseNode true } } environment { DOCKER_REGISTRY http://服务器IP:5000 APP_NAME my-vue-app IMAGE_TAG ${BUILD_NUMBER} } stages { stage(Checkout) { steps { checkout scm } } stage(Build) { steps { sh npm ci // 用 ci 替代 install更快更可靠 sh npm run build // 生成 dist/ 目录 } } stage(Build Docker Image) { steps { script { // 构建镜像基础镜像用 nginx把 dist/ 复制进去 def customImage docker.build( ${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}, -f Dockerfile -t ${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG} . ) docker.withRegistry(${DOCKER_REGISTRY}, docker-registry-credentials) { customImage.push() } } } } stage(Deploy) { steps { script { sh docker stop ${APP_NAME} || true docker rm ${APP_NAME} || true docker run -d \ --name ${APP_NAME} \ -p 80:80 \ --restartalways \ ${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG} } } } } }DockerfileFROM nginx:alpine COPY dist/ /usr/share/nginx/html/ COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80实操心得前端构建用npm ci而非npm install因为ci会严格比对package-lock.json确保依赖树和本地开发完全一致避免“在我机器上能跑”的问题。另外Dockerfile里COPY dist/必须在COPY nginx.conf之后否则 Nginx 配置不生效。5. 高频问题排查与避坑指南5.1 构建失败常见错误速查表错误现象根本原因解决方案我的实测耗时Permission denied: /var/jenkins_home/workspace/...Jenkins 容器内用户jenkins对挂载卷/data/jenkins无写权限sudo chown -R 1000:1000 /data/jenkins1000 是 jenkins 用户 UID30 秒Cannot connect to the Docker daemon at unix:///var/run/docker.sockDocker Socket 挂载路径错误或权限不足检查docker-compose.yml中/var/run/docker.sock:/var/run/docker.sock:ro确认宿主机 socket 存在且可读2 分钟Failed to push image: unauthorized: authentication requireddocker.withRegistry()未传凭据 ID或凭据 ID 拼写错误进入Credentials → System确认凭据 ID 和 Pipeline 中docker.withRegistry(..., id)一致1 分钟sh: mvn: not foundMaven 镜像未正确拉取或agent { docker { image ... } }拼写错误sudo docker exec -it jenkins-master sh手动运行docker run -it maven:3.9-amazoncorretto-17 mvn -v测试镜像5 分钟ERROR: No such container: my-appDeploy 阶段docker stop命令在容器不存在时返回非 0 状态导致 Pipeline 中断在sh命令前加 5.2 镜像体积过大问题如何把 1.2GB 的 SpringBoot 镜像压到 280MBSpringBoot 项目打成 Fat Jar 后Docker 镜像常超 1GB导致推送慢、启动慢。优化三板斧第一斧用分层构建Multi-stage Build# 第一阶段构建 FROM maven:3.9-amazoncorretto-17 AS builder WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline -B COPY src ./src RUN mvn clean package -DskipTests # 第二阶段运行只复制 jar不带 Maven FROM amazoncorretto:17-jre-alpine WORKDIR /app COPY --frombuilder /app/target/*.jar app.jar ENTRYPOINT [java,-Djava.security.egdfile:/dev/./urandom,-jar,app.jar]第二斧启用 BuildKit 加速在docker-compose.yml的 Jenkins 服务中加环境变量environment: - DOCKER_BUILDKIT1并在Jenkinsfile的Build Docker Image阶段docker.build()前加sh export DOCKER_BUILDKIT1第三斧清理构建缓存在Build阶段末尾加sh mvn clean // 清理 target/ 目录避免下次构建时 COPY 过大效果某电商后台项目优化前镜像 1.18GB优化后 276MB构建时间从 6 分钟降到 2 分钟 15 秒推送时间从 4 分钟降到 45 秒。5.3 权限问题终极解决方案Jenkins 用户组映射最顽固的权限问题往往源于 Jenkins 容器内用户UID 1000和宿主机 Docker 组GID 999不匹配。解决方法查宿主机docker组 GIDgetent group docker # 输出docker:x:999:jenkins # 999 就是 GID修改docker-compose.yml显式指定 GIDservices: jenkins-master: # ... 其他配置 group_add: - 999 # 不再写 docker直接写数字 GID重启sudo docker-compose down sudo docker-compose up -d这招治好了我遇到的所有Got permission denied while trying to connect to the Docker daemon报错。原理是Docker 守护进程只认 GID不认组名。容器内jenkins用户 UID 1000 加入 GID 999 组就能和宿主机docker组无缝通信。5.4 Pipeline 脚本调试技巧如何快速定位哪一行报错Pipeline 报错时日志常显示WorkflowScript: 42: Expected a step line 42但实际错误可能在sh命令内部。我的调试三步法缩小范围注释掉stages下除Checkout外的所有 stage确认能拉代码逐行验证在Build阶段的sh命令里先只写sh echo build start再加sh mvn -v再加sh mvn clean package每加一行就构建一次进入容器调试当某行sh报错立即在 Jenkins 控制台执行sudo docker exec -it jenkins-master sh # 然后手动运行报错的命令观察详细输出个人体会90% 的 Pipeline 问题都是sh命令里的路径错误如target/写成dist/或权限错误如npm install用了sudo。把命令拿到容器里手动跑一遍真相立刻浮现。6. 进阶实践让 Jenkins 真正融入研发流程6.1 Git 分支策略驱动部署dev/test/prod 环境自动分流很多团队卡在“测试环境怎么自动部署”。答案是用 Git 分支名触发不同 Pipeline。在 Jenkins 项目配置中Source Code Management → Branches to build填origin/dev→ 对应测试环境填origin/test→ 对应预发环境填origin/main→ 对应生产环境。然后在Jenkinsfile里用env.BRANCH_NAME判断environment { DOCKER_REGISTRY http://服务器IP:5000 APP_NAME my-app // 根据分支名动态设置镜像 tag 和部署端口 IMAGE_TAG ${env.BRANCH_NAME}-${BUILD_NUMBER} DEPLOY_PORT env.BRANCH_NAME main ? 8080 : env.BRANCH_NAME test ? 8081 : 8082 } stage(Deploy) { steps { script { sh docker stop ${APP_NAME}-${env.BRANCH_NAME} || true docker rm ${APP_NAME}-${env.BRANCH_NAME} || true docker run -d \ --name ${APP_NAME}-${env.BRANCH_NAME} \ -p ${DEPLOY_PORT}:8080 \ --restartalways \ ${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG} } } }效果推dev分支自动部署到http://服务器IP:8082推test分支