场景:服务器上已经跑着一套给老项目用的 Jenkins(8080 端口),新项目(myapp)需要一套完全独立的 Jenkins——独立端口、独立 home 目录、独立插件体系,互不影响。 系统:Huawei Cloud EulerOS 2.0 (x86_64),部署方式:Docker + docker-compose。 本文记录从环境调研到初始化、升级、工具配置的全过程,以及踩到的 4 个坑。 (文中密码、密钥均已脱敏,请替换成自己的。)
一、先看清楚家底:环境调研
1.1 系统源里有什么 Java?——一个坏消息
新项目后端是 Spring Boot 3.x,要求 Java 17+。按惯例先查系统源:
结果只有:
结论:HCE 2.0 的 yum/dnf 源里没有 java-21-openjdk,连 java-17 也没有,只有 1.8 和 11。直接 yum install java-21-openjdk 必然报"没有任何匹配"。
dnf 和 yum 在 HCE 上是同一个源,换命令没用。
这件事直接影响了后面的技术选型:所有 Java 都不装在系统上——Jenkins 本体用官方镜像(自带 JDK),构建用 JDK 来自 Adoptium 官方 tar.gz 解压包,应用运行用 Docker 镜像。系统层面零 Java 安装。
1.2 旧 Jenkins 是怎么部署的?
服务器上已有一套给 bid 项目用的 Jenkins,先摸清它的部署方式(照抄成熟经验,避开它的资源):
| |
关键信息:
| 项目 | 旧实例情况 | 对新实例的影响 |
|---|---|---|
| 端口 | 8080(Web)+ 50000(Agent) | 新实例必须换端口 |
| 编排目录 | /home/compose/ | 新实例用独立目录 |
| 版本 | 2.541.1 (LTS),镜像 jenkins/jenkins:lts | 可复用本地镜像,不用重新拉 |
| 运行 JDK | 镜像自带 Temurin 21.0.9 | 不用管 |
| 构建 JDK | 宿主机 /home/compose/jdk17(Temurin 17.0.18+8,Adoptium tar.gz 解压) | 可以只读挂载复用 |
| docker.sock + privileged | 任务里能直接操作宿主机 Docker | 新实例不挂,隔离 |
extra_hosts | 内网 Git git.example.com → 10.10.10.15,DNS 不解析 | 新实例必须照配,否则拉不了代码 |
| 已有任务 | 4 个 bid 项目任务,生产在用 | 一个字都不能动 |
另外确认宿主机资源充足(内存 15G 剩 13G,磁盘剩 76G),跑第二个 Jenkins 没压力。
二、方案设计:怎么算"完全隔离"
| 维度 | 旧实例 | 新实例(jenkins2) |
|---|---|---|
| 编排目录 | /home/compose/ | /home/compose-jenkins2/ |
| 容器名 | jenkins | jenkins2 |
| Web 端口 | 8080 | 8082 |
| Agent 端口 | 50000 | 50001 |
| home 卷 | ./jenkins_home(6.4G,197 个插件) | 全新空目录 |
| 运行用户 | root(privileged) | 镜像默认 jenkins(uid 1000) |
| docker.sock | 挂载 | 不挂(任务不能直接动宿主机 Docker) |
| .m2 仓库 | 挂宿主机 | 不挂,独立 |
| jdk17 | 读写挂载 | 只读挂载复用(:ro) |
选 8082/50001 之前先查端口占用:
ss -tln,确认 8080/50000/8081 都已被占,8082/50001 空闲。
三、创建 jenkins2
3.1 第一版 compose:先跑起来
docker-compose.yml:
注意
chown 1000:1000不能省:容器以 jenkins(uid 1000)运行,home 目录属主是 root 会起不来。
3.2 浏览器初始化
- 拿初始密码:
docker exec jenkins2 cat /var/jenkins_home/secrets/initialAdminPassword - 浏览器打开
http://<服务器IP>:8082,粘贴解锁 - 选 Install suggested plugins(推荐套装,含 Pipeline / Git / Credentials 等基础插件)
- 创建管理员账号,完成
两个提醒:
- 云服务器记得在安全组放行 8082。
- 如果插件下载慢,可以把更新中心换成清华镜像:
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json(Manage Jenkins → Plugins → Advanced settings → Update Site)。
3.3 坑 1:git.example.com 域名解析不了
旧实例 compose 里有 extra_hosts,第一版没抄这一条——内网 GitLab 域名 git.example.com 在 DNS 里不存在,不配的话流水线 clone 代码必然失败。补上:
四、坑 2:安全警告横幅 → 顺便升级到最新 LTS
初始化完成后,Manage Jenkins 页面顶部挂着红色横幅:当前 2.541.1 core 存在多个已知安全漏洞。
因为新实例还没建任何任务,升级零成本,直接升:
升级到 2.568.3(当时最新 LTS),红色漏洞横幅消失。
其余几条横幅的处理:
- “Pipeline: Groovy Libraries 有 CSRF 问题但无修复版本”——没修复版本,只能忽略;
- built-in node 安全提示、CSP 提示——确认自己会用 built-in node 构建后,点 Dismiss 即可。
旧实例(8080)不要顺手升:它跑着 bid 项目的生产构建,升级要另约时间窗口、先备份 jenkins_home。隔离的意义就在这里——两边版本可以不一样,互不影响。
五、装插件:只装两个
推荐套装已经覆盖了 Pipeline、Git、Credentials,额外只需要:
Manage Jenkins → Plugins → Available plugins,搜索勾选:
- NodeJS Plugin——前端构建用。Jenkins 本体只是调度壳子,JDK/Maven 的工具管理是核心自带的,Node 不是;没有它,流水线脚本里
tools { nodejs 'node22' }不认识,pnpm install/build直接 command not found。 - SSH Agent Plugin——部署用。流水线 Deploy 阶段用
sshagent(['凭据ID']) { ... }把私钥临时加载进 ssh-agent,实现免密 scp/ssh。
点 Install,勾选"安装完成后重启 Jenkins",等半分钟自动重启(不影响 8080 的旧实例)。
后续小插曲:SSH Agent 方案后来因凭据问题被弃用(改用容器内密钥文件,见本系列第二篇),但插件装着无害。
六、全局工具配置:jdk17 / maven3.9 / node22
Manage Jenkins → Tools,配三个工具。名字必须和流水线脚本里 tools {} 引用的一字不差。
6.1 JDK——坑 3:没有 adoptium 安装器
点 JDK 新增,打算让 Jenkins 自动装 Temurin 17,结果发现 Add Installer 下拉里没有 “Install from adoptium.net”(只有 Extract zip / Batch / Shell 三项,这是部分版本/网络环境下的常见情况)。
解决办法:不自动装,复用宿主机现成的 JDK 17——当年旧实例手工解压的 Adoptium Temurin 17 就在 /home/compose/jdk17。给 jenkins2 加只读挂载(compose 第三版,也是最终版):
| |
Tools 页面配置:
- JDK:Name 填
jdk17;取消勾选 Install automatically;JAVA_HOME 填/usr/local/jdk17。
只读挂载(
:ro)是个好习惯:新实例万一配错也伤不到旧实例在用的 JDK。
6.2 Maven
- Maven:Name 填
maven3.9;勾选 Install automatically → Install from Apache → 选 3.9.x 最新(实际装到 3.9.16)。
默认走 Apache 中央仓库慢,给容器内的 Maven 配阿里云镜像(宿主机写好,jenkins_home 是绑定挂载,容器内直接生效):
/home/compose-jenkins2/jenkins_home/.m2/settings.xml:
6.3 NodeJS
- NodeJS:Name 填
node22;勾选 Install automatically → Install from nodejs.org → Node.js 22.x LTS。
如果 nodejs.org 下载不动,可以换 npmmirror 的二进制地址:
https://registry.npmmirror.com/-/binary/node/v22.20.0/node-v22.20.0-linux-x64.tar.gz
七、坑 4:保存配置时报 HTTP 403
在 Tools 页面填好 JDK 的 JAVA_HOME,点 Save,弹错:
这不是配置填错了。 原因是:当天 jenkins2 容器被反复重建过好几次、还升过一次级(2.541.1 → 2.568.3),而浏览器里还是升级前打开的旧会话页面——后台的表单校验接口需要有效的 CSRF crumb,过期会话提交就被 403 拒绝。
解决:退出登录 → 重新登录 → 重新进 Tools 填一遍 → Save。 保存后最好回进页面确认值真的存进去了。如果重新登录后仍然 403,那才需要查容器日志(docker logs jenkins2)深挖。
八、建 Git 凭据
流水线要从内网 GitLab 拉代码,先建凭据:
Manage Jenkins → Credentials → System → Global credentials (unrestricted) → Add Credentials:
- Kind:Username with password
- Username / Password:git.example.com 的账号密码(账号要有 myapp-safe 组的读权限)
- ID 手动填
myapp-git(不填会自动生成 UUID,脚本里没法引用) - Create
九、收尾状态
| 项目 | 值 |
|---|---|
| 访问地址 | http://10.10.10.44:8082 |
| 版本 | 2.568.3 (LTS) |
| 编排文件 | /home/compose-jenkins2/docker-compose.yml |
| 工具 | jdk17(JAVA_HOME=/usr/local/jdk17)、maven3.9(3.9.16)、node22(22.x) |
| 插件(额外) | NodeJS Plugin、SSH Agent Plugin |
| 凭据 | myapp-git |
| 镜像仓库 | Maven 阿里云、Node npmmirror(备用) |
十、经验总结
- 先查系统源再定方案:HCE 2.0 源里最高只有 OpenJDK 11,想"一条 yum 装 JDK 17/21"会直接卡死;全程容器化 + 官方 tar.gz 是绕开这个问题的正解。
- 隔离 = 端口 + 目录 + 权限三件事:换端口、独立编排目录、不挂 docker.sock、不用 root 跑,两个 Jenkins 就是真正的两套系统。
- 成熟实例的配置是宝藏:旧实例的
extra_hosts(内网 Git 域名)、宿主机 jdk17,都是可以只读复用的现成资产——但复用一律:ro。 - 新建实例趁没任务赶紧升级,安全横幅不要拖;跑生产的实例升级另约窗口。
- Jenkins 的 403 表单错误八成是会话过期,重新登录比查日志快。
- 工具 Name 和脚本
tools{}引用必须一字不差(jdk17 / maven3.9 / node22),凭据 ID 要手动指定,不要用自动生成的 UUID。
下一篇:《从零到上线:用这套 Jenkins 部署前后端项目(MySQL/Redis 容器化)踩坑全记录》——包括 3306 之争、ssh-agent 凭据三连败、403 Forbidden、logo 消失之谜等 8 个实战坑。
