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

629 阅读9分钟

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

前置概念

CI 的含义

CI 的意思是 持续构建 。

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

CD 的含义

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

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

初始化环境

​ 从现在开始,我们就要真正实操 CICD 啦,建议搞一台新的服务器,避免搞乱环境,如果需要购买,可以参考文档**保姆级指南:购买阿里云 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 
安装
yum install -y java
安装 jenkinus

关键时刻到来,需要先配置下配置 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

关闭防火墙

首先查看防火墙是否是开启状态,如果是Active: inactive(dead)则说明已经是关闭态了。

systemctl status firewalld.service

如果是active(running)则在运行;则运行如下命令进行关闭即可

systemctl stop firewalld.service
启动 jenkins 服务

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

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

systemctl start jenkins

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

systemctl enable jenkins
访问 jenkins 服务

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

初始化 jenkins

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

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

新手入门:安装插件

​ 直接安装推荐的插件就好,但是点击前需要先去更改下 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

新手入门:配置用户

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

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

应用 jenkins

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

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

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

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

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

docker -v
docker pull node:latest
首先新建一个任务

添加要执行的脚本

构建任务

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

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

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

执行如下命令

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 插件的下载

等待安装重启完成

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

先找到系统全局配置

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

此时我们就有了 node 环境啦

测试 node 环境

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

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

node -v

执行任务

看到状态未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 任务的配置页,添加。

这时它会提示没有权限

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

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

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

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

配置脚本

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

  1. 安装依赖,进行项目构建
  2. 执行Dockerfile文件生成镜像【执行命令为docker build -t [镜像名]:[版本号] [Dockerfile 文件的所在路径],假定此处镜像名为react-project
  3. 根据新镜像启动服务(为避免端口冲突,先关闭掉镜像下所有服务)

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

#!/bin/sh

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

脚本添加位置如图

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

构建任务

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

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

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

【ip:3000】

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