背景
目前笔者所在的小公司的前端项目还是推送到git仓库后由另一名后端拉取代码到他电脑上再build,然后再手动同步到服务器上,比较麻烦,而且出现一个bug就要立即修复,笔者一天要说100次“哥,代码更新了,打包上传下吧,球球了”,终于我实在受不了了(上传代码的这位哥也受不了了),于是想通过 Jenkins 实现简单的前端项目自动打包部署。
通过 docker 安装 Jenkins
通过 ssh 连接上局域网服务器 192.168.36.2,在 home 目录下新建了一个 Jenkins 文件夹,后续我们的配置文件就放在其中。
创建docker-compose.yml
:
Jenkins 启动后会挂在8080
端口上,本文笔者将其映射到8999
端口,读者可以自行更改。
关键在于将容器中的/var/jenkins_home
目录映射到宿主机的/root/jenkins/jenkins_home
目录,这一步相当于将 Jenkins 的所有配置都存放在宿主机而不是容器中,这样做的好处在于,后续容器升级、删除、崩溃等情况下,不需要再重新配置 Jenkins。
使用:wq
保存后可以开始构建了:
这一步会构建容器并启动,看到如下信息就说明成功了:
查看一下容器是否在运行:
这个时候通过http://192.168.36.2:8999
就可以访问 Jenkins 了。
Jenkins 初次配置向导
解锁
第一次打开会出现向导,需要填入管理员密码,获取密码有三种方式:
- 通过宿主机
- 通过 docker 进入容器
与方法一类似,因为目录映射,这两个目录其实是同一个。
- 通过查看 docker log
会出现一大串,最后能找到密码:
填入密码,点击继续。
安装插件
选择安装推荐插件即可。
安装插件可能会非常慢,可以选择换源。
更换 Jenkins 插件源(可选)
有两种方法:
- 直接输入地址:
http://192.168.36.2:8999/manage/pluginManager/advanced
,在Update Site
中填入清华源地址:
点击Submit
提交保存,并重启容器。
- 直接更改配置文件:
宿主机中操作:
替换其中的地址,然后重启容器即可。
创建用户
这一步建议用户名不为 admin ,不然会出现奇怪的问题,比如密码登录不上,需要用上一部的初始密码(2bf4ca040f624716befd5ea137b70560)才能登录。
我这里创建了一个 root 用户(只是名字叫 root,防止用户名太多记不住而已)。
点击保存并完成。
实例配置按需调整即可,直接下一步,Jenkins 就准备就绪了。
至此 Jenkins 安装就算完成了。
安装插件
笔者是一名前端,因此以前端项目为例。
前端项目的打包需要 node 环境,打包完成后通过 ssh 部署到服务器上,并且构建结果通过钉钉机器人推送到群里,因此需要三个插件。
- NodeJS
- Publish Over SSH
- DingTalk(可选)
在 系统管理 → 插件管理 → Available plugins 中搜索并安装。
勾选安装后重启,让插件生效。
插件配置
我们安装了三个插件,分别进行配置。
NodeJS
这个插件可以在不同的项目中使用不同的 node 环境,例如 A项目 使用 node14,B项目 使用 node20 这样。
进入 系统管理 → 全局工具配置 → NodeJS 安装 (在最下面)
点击新增:
默认的这个使用的是 nodejs.org 的官方源,虽然现在 nodejs.org 的官方源国内访问也还可以,但为了保险起见,笔者还是换成阿里巴巴源。
点击红框里的 X 删除当前安装,在点击新增安装,选择 Install from nodejs.org mirror
。
镜像地址填入https://mirrors.aliyun.com/nodejs-release/
,版本按需选择,笔者这里选择的是 node20-lts,并且安装了包管理工具 pnpm
,如果读者的项目需要别的全局安装的包,也可以写在 Global npm packages to install
,比如 yarn
、cnpm
之类的。
记得起一个别名:
配置好后点击保存。
一般来说,在使用 npm 时,需要更改 npm 的源,同样在 Jenkins 中也是可以的。
安装完 NodeJS 插件后,系统设置中会多一项 Managed files
进入后选择左侧的Add a new Config
,然后选择 Npm config file
,然后点击 Next
。
新增一个 NPM Registry
,填入阿里巴巴镜像源:http://registry.npmmirror.com
。
至此 NodeJS 相关的配置就完成了。
SSH Server
打包后需要通过 SSH 部署到服务器上,因此需要先配置好 SSH 服务器。
打开 系统管理 → 系统配置 → Publish over SSH (在最下面):
然后根据实际情况进行填写:
字段 | 解释 |
---|---|
Name | 显示在 Jenkins 中的名称,可随意填写 |
Hostname | 服务器地址,ip 或 域名 |
Username | SSH 登录的用户名 |
Remote Directory | SSH 登录后进入的目录,必须是服务器中已经存在的目录,设置好之后所有通过 SSH 上传的文件只能放在这个目录下 |
这里笔者使用用户名-密码的方式登录 SSH,如果要通过 SSH Key 的方式的话,需要在字段 Path to key
填入 key 文件的地址,或者直接将 key 的内容填入 Key
字段中:
image-20240403144737759
设置好可以通过Test Configuration
,测试 SSH 连通性:
出现 Success
代表 SSH 配置成功。
钉钉通知(可选)
如果不需要通过钉钉通知,可以不装 DingTalk 插件,并跳过本节内容。
钉钉部分设置
该功能需要一个钉钉群,并打开钉钉群机器人:
点击添加机器人,选择自定义:
image-20240403145604092
这里笔者的安全设置选择了加签:
将签名保存下来备用。
点击完成后,出现了钉钉机器人的 Webhook 地址。
将地址保存下来备用。
至此钉钉部分的设置就结束了。
Jenkins 部分
打开 系统设置 → 钉钉 (在最下面的未分类中):
image-20240403145150439
根据需要配置通知时机:
image-20240403145231249
然后点击机器人-新增:
将刚刚的钉钉机器人的签名和 Webhook 地址填入对应的地方,并点击测试:
此时钉钉机器人也在群中发了消息:
至此钉钉机器人配置完毕。
创建任务(job)
本文中,笔者将以存储在 Git 仓库中的项目为例。
Github 项目
「注意,如果想让 Github 项目全自动构建的话,需要你的 Jenkins 能被公网访问到,例如部署在云服务器上,像笔者这样部署在本地局域网中,是无法实现“提交代码 → 自动构建 → 自动部署”的,只能实现“提交代码 → 手动点击开始构建 → 自动部署”」
如果在 Jenkins 新手向导里选择了 安装推荐插件,那么现在就不需要额外安装 Github 相关的插件了,否则的话需要手动安装 Github 相关的插件:
创建项目
选择 Dashboard → 新建任务:
选择构建一个自由风格的软件项目
,点击确定。
General
这部分可以添加钉钉机器人:
image-20240403151545166
源码管理
这里选择 Git:
输入仓库地址:https://github.com/baIder/homepage.git
image-20240403151822101
由于笔者这是一个私有仓库,因此会报错。
在下面的Credentials
中,添加一个。
「注意,这里的用户名是 Github 用户名,但是密码不是你的 Github 密码,而是你的 Github Access Token!!!」
image-20240403152324115
image-20240403152429183
可以在这里创建 Token,需要勾选 admin:repo_hook
、repo
权限。
image-20240403152535951
image-20240403152729685
这里的报错是网络问题,连接 Github 懂得都懂。
image-20240403152824725
分支可以根据实际情况选择。
构建触发器
勾选GitHub hook trigger for GITScm polling
,这样在 Git 仓库产生提交时,就会触发构建,属于是真正的核心。
image-20240403153134664
构建环境
勾选 Provide Node & npm bin/ folder to Path
image-20240403153444910
Build Steps
到这里,可以理解为 Jenkins 已经将仓库克隆到本地,并且已经安装好了node
、npm
、pnpm
,接下来就是执行命令:
image-20240403153625159
我们需要执行命令:
node -v pnpm -v rm -rf node_modules rm -rf dist pnpm install pnpm build
这里的pnpm build
需要按情况更换为package.json
中设定的命令。
image-20240403153850007
image-20240403153750787
构建后操作
经过所有的流程到这里,项目应该已经打包在dist
目录下了。现在可以通过 SSH 将打包好的产物上传到服务器上了:
image-20240403154044658
image-20240403155757484
这里的 Source files
字段一定要写成dist/**/**
,如果写成dist/*
,则只会将第一层的文件上传。
Remove prefix
需要填写,否则会将dist
这个目录也上传到服务器上。
Remote directory
是相对于配置 SSH Server 时的 Remote directory
的,本例中就是 /data/sites/homepage
。
Exec command
是文件上传后执行的命令,可以是任何命令,可以是让nginx有权限访问这些数据,重启nginx等等,根据服务器实际情况更改。
❝
当然也可以在
Build Steps
中 build 完成后将 dist 目录打包,然后在通过 SSH 将压缩包上传到服务器,然后在Exec command
中解压。❞
至此所有的配置已经完成,保存。
测试
点击左侧的 立即构建:
image-20240403154858929
image-20240403154950197
第一次构建会比较慢,因为需要下载node,安装依赖等等,可以从控制台看到,命令都如期执行了:
image-20240403155359524
构建成功,钉钉机器人也提示了(因为 Github 访问失败的原因,多试了几次):
image-20240403155855959
笔者已经配置好了nginx,因此可以直接访问网页,查看效果:
image-20240403160008179
通过 Git 提交触发构建
目前虽然构建成功了,但是需要手动点击构建,接下来实现如何将代码提交 Git 后自动触发构建。
打开仓库设置 → Webhooks 添加一个:
image-20240403160353025
这里的 Payload URL
就是 Jenkins 地址 + /github-webhook
,例如笔者的就如图所示。
但是由于笔者的 Jenkins 部署在本地局域网,因此是不行的,Github 肯定是无法访问到笔者的局域网的,有公网地址的读者可以试试,在笔者的阿里云服务器上是没有问题的。所以目前如果是 Github 项目的话,笔者需要提交代码后手动点击 立即构建:
image-20240403161026497
Gitlab 项目
实际上笔者所在公司是在局域网中部署了 Gitlab 的,因此针对 Gitlab 项目的自动化才是核心。
安装 Gitlab 插件:
image-20240403161442736
安装完毕后重启 Jenkins。
获取 Gitlab token
与 Github 的流程类似,也需要在 Gitlab 中创建一个 token:
image-20240403161807711
创建好之后保存 token 备用。
在 Jenkins 中配置 Gitlab
打开 Jenkins → 系统管理 → 系统配置 → Gitlab
image-20240403162301361
这里需要新建一个Credentials
,点击下方的添加:
类型选择GitLab API token
,将刚刚保存的 token 填入到 API token
字段中。
image-20240403162144399
点击Test Connection
:
image-20240403162651637
出现Success
说明配置成功。
创建项目
大多数过程与 Github 项目雷同。
General
会多出一个选项,选择刚刚添加的:
image-20240403163406501
源码管理
Git 仓库地址填 Gitlab 仓库地址,同样会报错,添加一个Credentials
便可解决:
image-20240403163538105
用户名密码填登录 Gitlab 的用户名密码即可。
构建触发器
按需选择触发条件,这里笔者仅选择了提交代码:
这里红框中的 url 需要记下,后面要用。
image-20240403164252265
其他配置
与 Github 项目相同。
测试构建
点击立即构建,查看是否能构建成功:
image-20240403163945821
构建成功:
image-20240403164002293
提交代码自动构建
进入 Gitlab 仓库 → 设置 → 集成:
这里的 url 填入刚刚 Jenkins 构建触发器 中红框内的 url 地址。
image-20240403164203308
看情况是否开启 SSL verification。
点击 Add webhook:
image-20240403164449921
测试一下:
image-20240403164513668
可以看到 Jenkins 那边已经开始构建了:
image-20240403164551282
构建成功:
image-20240403164606737
测试 Git 提交触发构建
目前页面:
image-20240403164712339
我们将v2.0-f
改成v2.0-g
:
image-20240403164817371
提交代码,Jenkins 开始了自动构建:
image-20240403164852625
构建成功,页面也发生了变化:
image-20240403164912343
至此,Gitlab 提交代码后自动打包并部署至服务器的流水线就完成了。
后记
本文实现了从提交代码到部署上线的自动化工作流,适合小公司的小型项目或自己的演示项目,大公司一定会有更规范更细节的流程,笔者也是从实际需求出发,希望本文能帮助到各位,由于笔者也是第一次使用 Jenkins,如有不足或错误之处,请读者批评指正。