基于Docker的前端自定义实现CI/CD

635 阅读6分钟

前端自定义实现CI/CD

初识Docker

在我们开发过程中肯定存在这么一个场景,我们开发完一套程序,在自己本机运行正常;

测试阶段,部署到测试环境发现跑不起来,解决完之后;

上线阶段,发现线上环境跑不起来~

那要怎么解决呢?

虚拟机

初期,我们使用虚拟机技术,将可运行的环境的进行复制粘贴

但是,虚拟机由于需要重新部署一个底层操作系统,而一个操作系统动则几G到几十G,占用内存,且启动也相对缓慢费时的

v2-c20cb49c88034e73e09059668b8cecfb_720w.webp

v2-0f6ede7f0b920b5d0d5571c937a04838_720w.webp

那么,有没有一种技术可以鱼与熊掌兼得,既能隔离环境,又方便部署呢?

容器技术

容器一词的英文是container,其实container还有集装箱的意思,集装箱绝对是商业史上了不起的一项发明,大大降低了海洋贸易运输成本。让我们来看看集装箱的好处:

  • 集装箱之间相互隔离
  • 长期反复使用
  • 快速装载和卸载
  • 规格标准,在港口和船上都可以摆放

容器技术应运而生,与虚拟机有所不同

  • 通过操作系统实现隔离不同,容器技术只隔离应用程序的运行时环境(指运行时程序运行依赖的各种库以及配置),但容器之间可以共享同一个操作系统
  • 占用资源更少,同样规格硬件上可以部署更多容器
  • 启停速度更快,几乎瞬间启动

v2-907214eadd65987e84a0751c08143f91_720w.webpDocker就是容器技术的集大成者

Docker中有这样几个概念:

  • Dockerfile
  • Image
  • Container

类比一下,简单的把image理解为可执行程序,container就是运行起来的进程。

那么写程序需要源代码,那么“写”image就需要dockerfile,dockerfile就是image的源代码,docker就是"编译器"

这里我们使用Docker来模拟多台机器之间的协作,实现建议的CI/CD流程

Docker安装&使用

安装Docker

brew install --cask docker

安装可视化界面

image-20240312204909531.png

# 从docker-hub中查找portainer镜像
docker search portainer
# 找到并安装
docker pull portainer/portainer
# 启动镜像
docker run -d -p 9000:9000 -name portainer -restart always -v /var/run/docker/sock:/var/run/docker.sock -v portainer_db:/data portainer/portainer

或者通过Docker Dashboard启动即可

image-20240312205247712.png

image-20240312205318471.png

访问Portainer

localhost:9000

image-20240312205440934.png 现在我们借助Docker来搭建一套CI/CD

CICD流程图.drawio.png

CI之Jenkins

部署Jenkins

选择Jenkins镜像进行部署

image-20240312205559341.png 默认情况下本机映射端口会在启动时自动分配,由于是自动分配,每次重启会变,这里为了演示方便,写死为60001

image-20240312210454839.png

可以看到已经部署成功,秒启动

image-20240312210546114.png

访问一下

image-20240312210608612.png

找到初始密码

image-20240312210655801.png

image-20240312210715533.png

image-20240312210742628.png

傻瓜式安装即可

image-20240312210833950.png

可能需要多次重试安装才能完成所有插件的成功

也可以尝试将插件源改成国内的源

如清华源:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

image-20240313090016909.png

创建管理员账号

image-20240313085146910.png

进入主页

image-20240313085218062.png

最好重启一下,让前面安装的插件生效

image-20240313085723574.png

构建CI任务

配置git

image-20240313092613080.png

生成ssh

进入jenkins控制台

image-20240313100321994.png

生成ssh钥匙对

image-20240313100804006.png

配置对应的公钥到gitlab

image-20240313101102237.png

配置CI任务

image-20240313091845467.png

image-20240313091909137.png

配置源码拉取

image-20240313105849136.png

配置ssh秘钥

image-20240313105825133.png

配置构建脚本

image-20240313103257630.png

image-20240313103416151.png

#!/bin/bash
#下载工作区npm包
npm install 
#删除dist目录下的所有文件,dist目录即为当前jenkins工作区打包后的文件。
rm -rf ./dist/*
#执行打包命令
npm run build
#打包
zip -r dist.zip dist

保存后触发手动触发一下构建

image-20240313103602464.png

可以发现,报错了,查看下控制台日志

image-20240313114715141.png

可以发现,缺少node环境和zip工具

配置构建环境

安装node环境

image-20240313114810277.png

image-20240313120021916.png

image-20240313120109472.png

配置CI过程中注入node环境

image-20240313140557232.png

安装zip工具

打开控制台

apt update && apt install zip

触发构建

可以看到,已经构建成功

image-20240313141612322.png

但是此时构建的结果是没有保留下来的

image-20240313143140752.png

归档成品

image-20240313141702364.png

image-20240313141717118.png

image-20240313141755576.png

重新构建,可以看到构建后的归档成品

image-20240313143203569.png

至此,我们初步完成了构建流程

进一步,我们配置gitlab推送触发自动构建的过程

配置推送事件触发自动构建

image-20240313102154750.png

生成token

image-20240313102645742.png

在gitlab侧添加钩子

其中回调地址从上面可以看到为http://0.0.0.0:60001/project/Vue3,实际配置需要将IP替换为实际IP地址

image-20240313102750579.png

点击测试一下

image-20240313143456551.png

image-20240313143520694.png

再进一步,我们把Jenkins的构建状态同步到gitlab

构建状态同步gitlab

配置Gitlab API权限

安装GitLab API插件

image-20240313092328100.png

配置gitlab

生成api token令牌

image-20240313093006181.png

image-20240313143846403.png

jenkins配置gitlab

image-20240313094225018.png

配置token

image-20240313093046262.png

image-20240313094357049.png

点击测试一下是否API是否可以调通

image-20240313143927302.png

添加构建后操作——同步构建状态

image-20240313144437981.png

image-20240313144447026.png

重新构建一下,构建完成后可以看到gitlab项目有对应的流水线标识

image-20240313144132927.png

至此,已经完成了CI的搭建

CD之WEB服务

安装SSH服务

web服务器我们直接采用Nginx镜像搭建,

image-20240313150117868.png

为了开放ssh服务,我们这里开放22端口

image-20240313150240690.png

image-20240313150338601.png

接着,我们进入控制台,安装ssh服务

apt update
apt install openssh-server

安装完成后,我们需要开放ssh服务root登录权限

# 需要安装vim以便修改配置
apt install vim
# 编辑ssh配置文件,开发root登录权限
vim etc/ssh/sshd_config
# 在文件末尾添加 
# PermitRootLogin yes

image-20240313150948500.png

重启ssh服务,生效配置

service ssh restart

修改ssh登录密码

passwd

测试SSH服务

回到jenkins控制台,测试连接下ssh服务

需要注意,docker启动的容器之间相互调用可以直接通过docker开放的ip

image-20240313151318391.png

因此在jenkins中调用则通过172.17.0.2连接web-nginx

image-20240313151457438.png

可以看到,连接没有问题

发送归档包到web服务器

安装插件Publish Over SSH

image-20240313151643672.png

配置ssh连接配置

image-20240313152347356.png

image-20240313153151320.png

配置完可以点击右下角测试一下是否连接成功

image-20240313153209803.png

增加构建后操作-发送&解压归档包

image-20240313152002649.png

image-20240313152558965.png

注意,这里用到了unzip,因此在Nginx服务器需要通过控制台安装下unzip工具

可以看到nginx服务目录下已经接收到了文件

image-20240313153415242.png

但是我们直接访问nginx地址,发现页面不对,这是为什么?

因为默认我们实际的入口文件还要再深入一级目录,到/usr/share/nginx/html/dist

这里我们简单修改下nginx配置文件

修改nginx配置

vim etc/nginx/conf.d/default.conf

修改根路径

image-20240313153758177.png

重启nginx服务,生效配置

nginx -s reload

至此,我们完成了web服务的配置

负载均衡

为了进一步模拟多机器部署情况,我们按照上面的方式多部署一台web服务

image-20240313154040776.png

接着我们部署一台nginx服务负责转发服务

image-20240313154119067.png

修改配置文件转发

vim etc/nginx/conf.d/default.conf

image-20240313154238040.png

重启nginx服务,生效配置

nginx -s reload

最后我们访问nginx服务0.0.0.0:9000,就会自动帮我们转发到已经配置好的两台web服务器上

CICD流程图.drawio.png

Refrences: