什么是CI/CD
CI/CD 是持续集成(Continuous Integration)和持续部署(Continuous Deployment)的缩写。这是一种软件开发实践,可以帮助开发团队更频繁、更可靠地交付软件。
– 持续集成(CI):开发人员经常(每天或更频繁)将代码合并到共享存储库中。每次合并都会通过自动化的构建和测试来验证,以便尽早发现并修复问题。
– 持续部署(CD):这是一种自动化的软件发布过程,其中通过自动化的测试、构建和部署步骤,软件可以在任何时间点安全、快速地发布到生产环境。
这两种实践可以减少错误、提高软件质量,并加快新功能的交付速度。
为什么需要 CI/CD
CI/CD 是现代软件开发流程中的重要组成部分。它们的主要目标是提高软件开发的效率和质量,CI/CD 主要有以下优点:
1. 快速反馈:CI/CD可以在代码提交后立即运行测试和构建,快速发现并修复问题。
2. 减少人工错误:自动化的部署和测试过程可以减少人为的错误。
3. 提高开发速度:通过自动化的构建和部署,开发者可以更快地看到他们的更改在生产环境中的效果。
4. 提高软件质量:CI/CD可以确保每次代码更改都经过了测试和验证,从而提高软件的质量。
5. 更容易进行持续改进:CI/CD使得开发团队可以更频繁地进行小规模的更改,这样更容易进行持续改进。
在 web 项目中,可以使用如 Jenkins、Travis CI、CircleCI 等工具来实现 CI/CD。
前端项目部署
在实现 CI/CD 前,我们先来简单做一个本地服务,部署一下我们的前端项目
Nginx
基于 docker 部署一个 nginx 环境,Windows 下安装 docker 可参考这里 Docker 部署
# 拉取镜像
docker pull nginx:latest
# 创建容器
docker run -d -p 8080:80 --name nginxweb nginx
# 查看默认配置
cat ect/nginx/conf.d/default.conf
# 容器内安装 vim
apt-get install vim
# vim ect/nginx/nginx.conf
访问 localhost:8080
即可看到 nginx
欢迎页
将文件推送到 nginx 服务器
因为是在本地 docker 内,所以需要使用 docker 命令
docker cp [源文件目录] [容器id]:[目标目录]
比如 docker cp index.html [容器id]:/usr/share/nginx/html/
# 查看容器id
docker ps -a
通过脚本执行
新建 pub.sh
文件,输入如下内容, package.json
增加 scripts
命令: pnpm pub.sh
#!/usr/bin/env sh
echo "打包项目"
pnpm build
echo "打包完成"
cd dist
echo "发布项目"
docker cp . 591658bd739b:/usr/share/nginx/html/
echo "发布完成"
执行 pnpm pub
等待发布完成,再次访问 localhost:8080
可以看到部署项目
可以看到这个部署过程其实就是把项目文件(编译好的文件)传输至目标服务指定位置,这里我们通过脚本实现了一部分的自动化,在实际项目的运维过程,还需要根据不同情况进行不同流程的自动化,这就需要相应工具的配合了
接下来我们看看如何使用 Jenkins 把这个部署过程自动化
Jenkins
Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要
相关安装等的教程在 Jenkins 文档 上已经有详细的说明了,这里就不介绍
插件问题
如果插件下载失败,可以手动下载上传,以 Node.js 为例,可以在 Jenkins Plugins 中找到 NodeJS 插件并下载,然后在 系统管理–管理插件–高级–上传插件(Deploy Plugin} 里上传即可
手动上传可能也会失败,根据部分失败提示可能需要升级 Jenkins
如果是 docker 安装的 Jenkins 可前往 jenkins | 清华大学开源软件镜像站 下载对应版本包,然后执行命令以下命令替换 Jenkins 包,然后重启即可,路径默认是 /usr/share/jenkins
如果更改过则改为对应路径
docker cp jenkins.war [容器id]:/usr/share/jenkins
NodeJS
Jenkins 的 NodeJS 设置如下
可以新建一个自由风格的项目进行测试,按照如下配置
点击立即构建后会下载对应 nodejs 版本插件,下载比较久的也可以提前下载好对应的 node 包,基于docker的可以使用如下命令放到容器对应目录下
docker cp node-v18.16.1-linux-x64.tar.gz [容器id]:/var/jenkins_home/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs
创建流水线
需要安装 Pipeline
插件
新建任务选择流水线即可
Pipeline 定义
- Pipeline Script: 直接把脚本内容写到脚本对话框中
- Pipeline script from SCM (Source Control Management–源代码控制管理: 从 gitlab/github/git 上获得 pipeline JenkisFile脚本
这里选择 Pipeline script from SCM 配置项,该配置项可以把 pipeline 脚本写在项目的 jenkinsfile 文件内
pipeline {
agent any
tools {nodejs "node18.16.1"}
stages {
stage('first') {
steps {
nodejs(nodeJSInstallationName: 'node18.16.1') {
sh 'npm -v'
}
}
}
stage('build') {
steps {
sh 'pnpm build'
}
}
}
}
问题
以上例子可能会有node: not found
和 env: ‘node’: No such file or directory
问题,详细请查看 [JENKINS-34815] NodeJS plugin unable to install global NPM packages – issues
解决方案一
可参考 Alpine版的Jenkins插件的No such file or directory的解决方法_alpine no such file or directory_淼叔的博客-CSDN博客,不过这里处理得比较麻烦了,这样折腾的好处是,不同的项目有对应不同 node 版本要求,可以不用再做处理,直接选择对应的版本即可
解决方案二
如果不需要区分的可以考虑直接在 docker 容器内安装 nodejs、npm 等,可参考以下操作
# 进入容器
docker exec -u 0 -it [容器名] bash
# 下载 nodejs npm
apk add --no-cache nodejs npm
# 安装一些依赖,比如
npm i -g pnpm
如果是全局安装的也需要根据项目切换不同的 node 版本的可以结合 nvm 来管理 node 版本,在构建项目初始阶段先进行node 版本切换即可,这里就不详细介绍了
自动化构建
自动化构建可以理解为:当仓库发生变化时,通知 CI/CD 工具进行相应操作
github/gitee 项目页面,打开 Setting -> Webhooks -> Add webhooks 填写相关内容
webhook插件
jenkins 安装 Generic Webhook Trigger | Jenkins plugin 插件
然后进入 job 设置 构建触发器 模块
根据需要以及 github/gitee 项目 Add webhooks 页面填写的内容进行填写即可
Publish Over SSH 插件
上面我们项目写了个推送的脚本,那仅限于本地简单情况,实际项目中前端服务、CI/CD 工具在不同服务器上,这样构建后的文件推送就需要相应工具来完成
Publish Over SSH | Jenkins plugin 插件就可以很好的处理这件事
安装完成后在 job 构建后操作 配置选择 Send build artifacts over SSH,根据实际情况编写脚本处理文件上传即可
本地测试 webhooks
如果是本地测试的话可以使用 ngrok 来把本地服务暴露给公网,参考这篇 本地开发如何测试 Webhook
最后
本文基于 Jenkins 工具简单体验一下 CI/CD 工作流程,这还不是真正的 CI/CD,CI/CD 是注重实践的一种开发实践,个人认为写再多不如在项目中实践,切不要以为配置一堆 DevOps 流水线就是 CI/CD 实践了
实际上,流水线设计需要基于 业务场景 进行相应设计的,比如:与分支策略相关的流水线设计
、与研发活动相关的流水线设计
流水线设计遵循以下原则
- 确定变量:确定 构建/部署 变量如参数、代码地址、分支名、脚本、部署ip等,保证任务可复制性
- 变量命名规范化:标准化利于快速复制,有意义的命名有助于理解
- 一次构建多次部署:杜绝重复打包,有共性的可抽共性脚本,良好的设计方便维护
- 步骤标准化/原子化:构建等动作标准化避免重复写各种脚本,然后根据不同业务组装,如,提测、回归、每日例行构建等
- 快速失败:尽量把不稳定且耗时短的步骤放在流水线前面,这样反馈周期会短很
最后,清晰的代码结构、标准的环境配置 、原子化的流水任务,加上团队协作规范要求以及持续优化体验,才是真正的 CI/CD 实践