jenkins+docker 实现前端和nodejs服务端自动化发布

前言

现代软件工程都强调持续集成的能力,而持续集成的一个重要组成部分持续部署。也就是本文的重点,自动化部署。本文会从零开始讲述每个环节的原理和实现方法。

jenkins+docker安装

安装docker

只需要一句运行命令即可安装:

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

输入命令后回车等待一会看到下面的信息就是安装完成了:

root@iZwz92akl2vtt9nu4w6lq7Z:~# curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
# Executing docker install script, commit: 3d8fe77c2c46c5b7571f94b42793905e5b3e42e4
+ sh -c 'apt-get update -qq >/dev/null'
+ sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null'
+ sh -c 'curl -fsSL "https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg" | apt-key add -qq - >/dev/null'
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sh -c 'echo "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu focal stable" > /etc/apt/sources.list.d/docker.list'
+ sh -c 'apt-get update -qq >/dev/null'
+ '[' -n '' ']'
+ sh -c 'apt-get install -y -qq --no-install-recommends docker-ce >/dev/null'
+ sh -c 'docker version'
Client: Docker Engine - Community
 Version:           20.10.3
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        48d30b5
 Built:             Fri Jan 29 14:33:21 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.3
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       46229ca
  Built:            Fri Jan 29 14:31:32 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.3
  GitCommit:        269548fa27e0089a8b8278fc4fc781d7f65a939b
 runc:
  Version:          1.0.0-rc92
  GitCommit:        ff819c7e9184c13b7c2607fe6c30ae19403a7aff
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:

  sudo usermod -aG docker your-user

Remember that you will have to log out and back in for this to take effect!

WARNING: Adding a user to the "docker" group will grant the ability to run
         containers which can be used to obtain root privileges on the
         docker host.
         Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
         for more information.

执行一下查看版本的命令再次确认安装成功:

root@iZwz92akl2vtt9nu4w6lq7Z:~# docker version
Client: Docker Engine - Community
 Version:           20.10.3
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        48d30b5
 Built:             Fri Jan 29 14:33:21 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.3
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       46229ca
  Built:            Fri Jan 29 14:31:32 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.3
  GitCommit:        269548fa27e0089a8b8278fc4fc781d7f65a939b
 runc:
  Version:          1.0.0-rc92
  GitCommit:        ff819c7e9184c13b7c2607fe6c30ae19403a7aff
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

本文使用的服务器系统是Ubuntu 20.04 64位,其它系统安装过程类似。

在docker上安装jenkins

执行以下命令:

docker run \
  -u root \
  --rm \
  -d \
  -p 8080:8080 \
  -p 50000:50000 \
  -v jenkins-data:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  jenkinsci/blueocean

等待下载安装,看到下面的信息说明安装完成了:

root@iZwz92akl2vtt9nu4w6lq7Z:~# docker run \
>   -u root \
>   --rm \
>   -d \
>   -p 8080:8080 \
>   -p 50000:50000 \
>   -v jenkins-data:/var/jenkins_home \
>   -v /var/run/docker.sock:/var/run/docker.sock \
>   jenkinsci/blueocean
Unable to find image 'jenkinsci/blueocean:latest' locally
latest: Pulling from jenkinsci/blueocean
801bfaa63ef2: Pull complete 
755713f1a3c1: Pull complete 
eb3cc996a4d2: Pull complete 
53fff950d571: Pull complete 
f6936a1aec5a: Pull complete 
257a3874e67f: Pull complete 
a1322c53804d: Pull complete 
6f3525ef00e6: Pull complete 
d105e9324027: Pull complete 
3bd288623327: Pull complete 
0c464039fb0b: Pull complete 
25248a2f7ff6: Pull complete 
80aea1f6597d: Pull complete 
9507a0ecbe89: Pull complete 
90cd370947fb: Pull complete 
6dc19b8b34e0: Pull complete 
Digest: sha256:27955db4139f933fa831638f99608b0ceb504e88ce82bcbbc80e41bfcfdcca45
Status: Downloaded newer image for jenkinsci/blueocean:latest
1f2b65eac96879b8ab1717edc25ccf508bd2dac2702ac3e924ce74667227a190

更多安装细节请参考:jenkins安装

同样我们运行docker ps -a确认是否正确安装并启动了jenkins

root@iZwz92akl2vtt9nu4w6lq7Z:~#  docker ps -a
CONTAINER ID   IMAGE                 COMMAND                  CREATED       STATUS       PORTS                                              NAMES
1f2b65eac968   jenkinsci/blueocean   "/sbin/tini -- /usr/…"   2 hours ago   Up 2 hours   0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp   fervent_brown

看到以上信息说明jenkins已安装并启动了,这时候我们用浏览器打开:服务器地址:8080,可以看到以下页面:
image
需要输入的管理员密码在jenkins打印的日志中,我们回到服务器终端,执行以下命令:

docker logs 1f2b65eac968

其中1f2b65eac968jenkins容器的CONTAINER ID,在前面我们执行docker ps -a命令的时候可以查看到。
执行命令后在终端中找到这串字符串:

*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

f12938a211dc4402a7e679a71e1962e3

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************

复制中的随机字符串,回到浏览器,将字符串输入管理员密码的文本框中,然后点击继续按钮。经过一段时间的等待进入了如下页面,点击安装推荐的插件
image
接下来将进入插件安装的等待过程,安装完成后进入创建管理员的页面,填入相关信息创建管理员。
image
接下来进入实例配置页面,我们不做修改,点击保存并完成
image
到这里我们就成功安装了jenkins+docker的环境。

安装jenkins插件

阿里云OSS上传插件

插件:Aliyun OSS Uploader
作用:用于上传前端静态文件到阿里云的OSS上。

创建pipeline

jenkinspipeline也就是多分支流水线pipeline将完成我们一系列的自动化测试发布等任务。
点击页面左侧的打开 Blue Ocean
image
点击创建新的流水线
image.png
选择一个代码仓库类型,然后填入你的前端代码仓库地址,填入代码仓库的用户名和密码,点击创建流水线
image.png

创建前端代码测试、构建、上传cdn任务节点

进入pipeline编辑页面,点击+创建一个节点,命名为fe
点击设置将节点运行环境设置为:dockernode:14.8.0-alpine3.12node的版本号根据项目调整,最合理状态下,开发环境测试环境构建环境生产环境node版本应该全部一致。
image.png
下面我们开始添加步骤,展开步骤列表,点击添加步骤
注意:示例的前端项目基于vue cli,如果你直接使用webpack,相关的命令会有差异。

步骤1:安装依赖

步骤目的:安装前端的依赖,用于后续测试、构建等步骤。
步骤类型:Shell Script
内容:

npm install
步骤2:单元测试

步骤目的:运行单元测试,如果过程报错则整个任务会中断。
步骤类型:Shell Script
内容:

npm run test

注意:这里只是进行单元测试,实际情况可能还需要进行端到端等测试,只需要增加一个步骤即可。

步骤3:构建前端代码

步骤目的:如果测试通过,则进行前端代码的打包构建。
步骤类型:Shell Script
内容:

npm run build
步骤4:将index.html暂存起来

步骤目的:将构建完成后的前端入口html文件暂存起来,后续步骤需要使用。
步骤类型:Stash some files to be used later in the build
内容:
image.png

以上内容根据你项目的情况做目录和名称上的修改,如果是多page项目则需重复这个步骤多次,将多个入口html文件暂存起来。

步骤5:前端代码上传至阿里云的OSS

步骤目的:将构建完成的前端代码上传至阿里云的OSS(相当于cdn)。
步骤类型:阿里云OSS上传
内容:
image.png

创建服务端代码测试、构建、生成docker镜像节点

本文的服务端是nodejs语言,使用eggjs框架。如果使用php或者java作为后端语言,相关设置会有差异。
fe节点后面点击+创建一个节点,命名为service
下面我们开始添加步骤,展开步骤列表,点击添加步骤

步骤1:在GIT上拉取服务端代码

步骤目的:拉取git上服务端代码。
步骤类型:Git
内容:
image.png
其中凭证id需要到jenkins凭证管理中添加,如下图,填如git的用户名和密码,然后自定义一个凭证id
image.png

步骤2:将前端的入口html放在服务端代码指定目录

fe节点的步骤4中,我们将前端的index.html暂存起来,现在我们先进入服务端代码的特定目录(你想放置这个文件的目录),然后取出这个index.html放置在这个目录下。这样你的服务端代码在用户访问的时候返回这个index.html文件的内容即可。
步骤目的:进入服务端代码的指定目录
步骤类型:Change current directory
内容:
image.png
进入了服务端代码的app目录,并且通过子步骤将我们暂存的index.html放置在这个目录中。不同的服务端目录结构会有差异,请根据服务端项目结构来选择放置位置。

子步骤

在步骤2中添加一个子步骤
步骤目的:将暂存的index.html放置在当前目录
步骤类型:Restore files previously stashed
内容:image.png

步骤3:登录阿里云的容器镜像服务

阿里云的容器镜像服务用于存储docker的镜像,你也可以用docker自己创建一个镜像仓库。这里就不对此展开讨论。
步骤目的:后续步骤需要传输镜像到阿里云的容器镜像服务上,所以先登录。
步骤类型:Shell Script
内容:docker login -u [阿里云账号] -p [阿里云密码] [镜像仓库地址]
具体参数可以请查阅阿里云的相关文档。

步骤4:将服务端代码构建成镜像

步骤类型:Shell Script
内容:docker build -t [镜像仓库地址]:$BUILD_NUMBER
此步骤需要先配置Dockerfile文件,该步骤不在这里展开,你可以自行搜索相关资料。

步骤5:将镜像提交到阿里云的容器镜像服务上

步骤类型:Shell Script
内容:docker push [镜像仓库地址]:$BUILD_NUMBER

步骤6:将镜像运行到目标服务器上

步骤类型:Shell Script
内容:

ssh -o StrictHostKeyChecking=no root@[目标服务器ip]
docker rm -f [容器自定义名称] || true
docker run -d --name=[容器自定义名称] --network host [镜像仓库地址]:$BUILD_NUMBER

注意:

  1. 通常情况下会有多个服务器需要部署,这里作为示例只部署一台;
  2. docker rm是先移除服务器上旧的运行的容器;
  3. ssh免密登录需要在两台服务器上配置密匙,这方面的资料可以自行搜索;

其它细节

清除旧的镜像

在服务器上运行远程镜像的时候每次都会存储旧的镜像在服务器中,所以有必要每次运行新镜像前清理一下旧的镜像,可以使用下面的命令来清理掉相关的镜像:

docker rmi -f  `docker images | grep '[镜像的关键字]' | awk '{print $3}'` || true

你可能感兴趣的:(jenkins+docker 实现前端和nodejs服务端自动化发布)