保姆级指南:jenkins+docker构建部署react项目实战

avatar
公众号「 微医大前端技术 」

王志远,微医前端技术部医疗支撑组

前置概念

CI的含义

CI 的意思是 持续构建 。

负责拉取代码库中的代码后,执行用户预置定义好的操作脚本,通过一系列编译操作构建出一个 制品 ,并将制品推送至到制品库里面。常用工具有 Gitlab CI,Github CI,Jenkins 等。这个环节不参与部署,只负责构建代码,然后保存构建物。构建物被称为 制品,保存制品的地方被称为 制品库

CD的含义

CD 则有2层含义: 持续部署(Continuous Deployment) 和 持续交付(Continuous Delivery) 。

持续交付 的概念是:将制品库的制品拿出后,部署在测试环境 / 交付给客户提前测试。 持续部署 则是将制品部署在生产环境。

初始化环境

​ 从现在开始,我们就要真正实操CI、CD啦,建议搞一台新的服务器,避免搞乱环境,如果需要购买,可以参考文档 保姆级指南:购买阿里云ecs服务器。无论是新买的还是自己电脑,电脑基础环境如下

  • docker
  • git
  • java:jenkins基于java环境
  • jenkins

假定机器有了,基于centos,接下来我们就开始搭建服务吧

docker安装

yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce -y
systemctl start docker
systemctl enable docker

此处需要配置下docker镜像源为阿里云,不然之后docker下载镜像等操作都会巨慢

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://fwvjnv59.mirror.aliyuncs.com"]
}
EOF

修改后需要重载所有修改过的配置文件

sudo systemctl daemon-reload
sudo systemctl restart docker

git安装

yum install git -y

此处需要对git进行下初始化,即生成ssh公私钥

ssh-keygen -t rsa -C "你的邮箱"

生成成功后,公私钥将存放在/.ssh/下,可以通过如下命令查看公钥,将之配置在github或码云这类平台上从而使得对应私钥具有操作仓库的权限

cat ~/.ssh/id_rsa.pub 

扩展:可以通过如下命令获取私钥,此处并不需要,但在后期配置jenkins权限时需要,可以留意一下

cat ~/.ssh/id_rsa 

java安装

yum install -y java

安装jenkins

关键时刻到来,需要先配置下配置jenkins的yum源

[root@jenkins ~]# wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
[root@jenkins ~]# rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

然后进行下载即可

yum install jenkins -y

如果很慢,直接ctrl+c中止原命令,执行如下命令通过清华大学地址下载

wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/latest/jenkins.war

到此,我们关于CI的最简洁版环境也就搭建好啦

初识jenkins

启动jenkins服务

jenkins可以理解为就是一个java项目,目标为提供一个面向软件持续集成的软件平台,见下图更为直观

image-20211031155138244

既然是一个项目,自然我们需要启动它从而启动一个服务,运行如下命令启动jenkins

systemctl start jenkins

如果想开机自启动,建议执行下面这个命令

systemctl enable jenkins

访问jenkins服务

那如何验证自己是否成功呢?自然是访问这个服务,jenkins默认服务提供的端口为8080,在浏览器输入ip:8080(如果是阿里云服务器,记得去配置安全组开放这个端口),进入Jenkins登录页面,如果出现如下界面,说明成功啦

img

初始化jenkins

接下来,我们来做一些第一次启动jenkins的初始化工作,如果是已经用过的同学,可以直接跳过这一章;

首先,需要一个密码,jenkins会在启动时将密码写入指定目录下,去cat一下复制粘贴就好

img

新手入门:安装插件

​ 直接安装推荐的插件就好,但是点击前需要先去更改下jenkins插件的镜像,不然会巨慢

sed -i 's/http:\/\/updates.jenkins-ci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' /var/lib/jenkins/updates/default.json && sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' /var/lib/jenkins/updates/default.json

image-20211031202526757

新手入门:配置用户

img

img

配置地址,这个一般直接下一步就好

img

如果出现下面这种界面,说明你初始化工作完成啦,开始enjoy your jenkins吧!

lmzf

img

应用jenkins

既然是【面向软件持续集成的软件平台】,自然需要做到如下两点

  • 如git、node、nginx等多应用的集成
  • 将多个应用的工作集成在一个任务中,jenkins管控内部细节

这就意味着jenkins是以任务为单元的

应用案例:设定通过docker下载node的任务

让我们以查看docker版本和通过docker下拉node镜像为例,新建一个任务,其实就是执行如下命令,只不是我们希望通过jenkins去管控,因为这样就代表以后一些复杂的脚本也可以通过任务的形式去自动化执行了

docker -v
docker pull node:latest

首先新建一个任务

image-20211031203642233

image-20211031203758147

image-20211031203916825

添加要执行的脚本

image-20211031204629002

构建任务

这时我们就完成任务的新建了,接下来我们开始构建这个任务吧!

先返回项目详情,然后点击立即构建,最后进入构建任务详情去看下日志,如果最后输出为STATUS:SUCCESS,说明成功啦

2021-10-31 20.48.12

补充:如果出现下面这个失败报错,说明是【jenkins】这个用户没有权限去访问docker这个服务,所以我们需要将用户添加进这个服务对应的组中

image-20211031205208396

执行如下命令

gpasswd -a jenkins docker

然后更新下即可

newgrp docker

应用案例:编译react项目

​ 接下来,我们来实操一下,目标很简单:让jenkins帮我们做到如下几步

  1. 执行构建命令处理一个存储在git或码云上的react项目,会生成一个build目录
  2. 启动一个nginx服务,再把这个build下的内容移动到nginx的静态文件目录下

这样服务器上就有了对应的服务,我们可以直接访问nginx服务端口从而访问项目,就可以做到对一个项目自动构建、自动部署提供服务,等后期接入了git或码云上传的钩子后,我们就可以实现自动化集成或自动化部署啦,这其实也就是我们说的CICD。

搭建node环境

要想编译react项目,起码得在jenkins服务中存在node服务,而这个服务是通过插件的形式提供的,大致思路为:

  1. 先进行node插件的下载
  2. 安装完插件后,全局配置中心就会出现对应的服务,我们选择指定版本后启动

这样就实现了jenkins中提供对应node服务的需求。知道了思路,那我们就开始实现吧!

首先,我们需要先进行node插件的下载

image-20211031210754382

image-20211031211927487

image-20211031212410608

等待安装重启完成

然后,我们需要在jenkins全局配置中添加node

先找到系统全局配置

image-20211031212534391

安装指定版本,选择从镜像中安装

image-20211031212712875

此时我们就有了node环境啦

测试node环境

接下来,我们在执行任务时应用我们创建的node环境,先创建一个任务,流程同之前,唯一不同的是在最后一步需要选择node环境,选择我们自己的版本即可

image-20211101072442872

我们在任务中执行如下脚本

node -v

image-20211101072818896

执行任务

2021-11-01 07.26.32

看到状态为SUCCESS并且输出了node的版本,说明搭建node环境成功啦

创建react项目

接着,我们在本地创建一个react项目(假定名字为ci-pro)并上传到码云,这个我们直接在本机上初始化下,然后推送到码云上就好;

使用脚手架

npm版本6+可直接执行

npx create-react-app ci-pro

或者版本低,就得本地安装执行了

create-react-app ci-pro

如果之前没有安装过这个脚手架,需要先执行下面这个命令进行安装

npm install -g create-react-app

等待安装完成了,我们就会有如下目录结构

.
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   ├── reportWebVitals.js
│   └── setupTests.js
└── yarn.lock

接入nginx

根据之前的思路,我们需要在项目编译后将产物放在nginx的静态资源目录下,然后通过nginx提供服务,那自然我们需要接入nginx服务,先实现nginx的配置文件

创建对应文件

mkdir conf && vi conf/default.conf

指定静态资源目录

default.conf文件内容

server {
    listen 80;
    server_name _;
    root /etc/nginx/html;
} 

此处我们通过docker提供nginx服务,涉及到移动目录、配置自定义配置文件等动作,我们需要自定义镜像,这就需要我们去实现自己的Dockerfile

创建对应文件

vi Dockerfile

做到如下两点:

  1. 将jenkins执行打包命令后产生的build目录移到nginx的静态资源目录下
  2. 指定自定义的配置文件
FROM nginx:1.15
COPY build /etc/nginx/html
COPY conf /etc/nginx

至此,我们就完成了本地项目的搭建,再关联下远端仓库,推送下就可以啦,看下现在的目录树

.
├── Dockerfile
├── README.md
├── conf
│   └── default.conf
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   ├── reportWebVitals.js
│   └── setupTests.js
└── yarn.lock

配置jenkins对仓库的权限

假定我们拿到了仓库的ssh地址,那就进入我们jenkins任务的配置页,添加。

image-20211101090817886

这时它会提示没有权限

image-20211101091000994

原因很简单,本机的公私钥对,将公钥配在码云上,自然本机有操作远程仓库的权限,但jenkins服务器上是没有私钥的,所有我们需要在jenkins中配置私钥从而获取权限,在哪配置呢?

配置 => 源码管理 => Git => Repositories -> Credentials => 添加 => SSH Username with private key

image-20211101091149354

image-20211101091212114

image-20211101100530734

关于获取私钥的方式,可以查看git安装模块内容

到此,我们就完成了jenkins关于git的配置

配置脚本

回到jenkins,配置在构建任务时要执行的脚本,要做到如下两点

  1. 安装依赖,进行项目构建
  2. 执行Dockerfile文件生成镜像
  3. 根据新镜像启动服务(为避免端口冲突,先关闭掉镜像下所有服务)

脚本内容如下(如果是云服务器,注意在控制台开放端口)

#!/bin/sh

npm install --registry=https://registry.npm.taobao.org
npm run build
docker build -t ci-project .
docker kill $( docker ps  | awk '/ci-project/ {print $1}')
docker run -d -p 3000:80 ci-project

脚本添加位置如图

image-20211101113945743

至此,我们的配置工作就大功告成,再接再厉,开始构建!

构建任务

和之前没啥差别,返回任务详情,点击立即构建即可

image-20211101114518682

当开始构建时,可以去查看构建任务详情,从而确定是否成功

image-20211101114618681

成功的话,尝试访问下服务

【ip:3000】

如果能出现如下react服务界面,说明成功啦!

image-20211101160839584

副本_副本_未命名_自定义px_2022-01-06-0.gif