前言
现代软件工程都强调持续集成的能力,而持续集成的一个重要组成部分持续部署。也就是本文的重点,自动化部署。本文会从零开始讲述每个环节的原理和实现方法。
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
,可以看到以下页面:
需要输入的管理员密码在jenkins
打印的日志中,我们回到服务器终端,执行以下命令:
docker logs 1f2b65eac968
其中1f2b65eac968
是jenkins
容器的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
*************************************************************
*************************************************************
*************************************************************
复制中的随机字符串,回到浏览器,将字符串输入管理员密码
的文本框中,然后点击继续
按钮。经过一段时间的等待进入了如下页面,点击安装推荐的插件
。
接下来将进入插件安装的等待过程,安装完成后进入创建管理员的页面,填入相关信息创建管理员。
接下来进入实例配置页面,我们不做修改,点击保存并完成
。
到这里我们就成功安装了jenkins+docker
的环境。
安装jenkins插件
阿里云OSS上传插件
插件:Aliyun OSS Uploader
作用:用于上传前端静态文件到阿里云的OSS上。
创建pipeline
jenkins
的pipeline
也就是多分支流水线
,pipeline
将完成我们一系列的自动化测试发布等任务。
点击页面左侧的打开 Blue Ocean
:
点击创建新的流水线
选择一个代码仓库类型,然后填入你的前端代码
仓库地址,填入代码仓库的用户名和密码,点击创建流水线
创建前端代码测试、构建、上传cdn任务节点
进入pipeline
编辑页面,点击+
创建一个节点,命名为fe
。
点击设置将节点运行环境设置为:docker
,node:14.8.0-alpine3.12
,node
的版本号根据项目调整,最合理状态下,开发环境
、测试环境
、构建环境
、生产环境
的node
版本应该全部一致。
下面我们开始添加步骤,展开步骤列表,点击添加步骤
。
注意:示例的前端项目基于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
内容:
以上内容根据你项目的情况做目录和名称上的修改,如果是多page项目则需重复这个步骤多次,将多个入口html
文件暂存起来。
步骤5:前端代码上传至阿里云的OSS
步骤目的:将构建完成的前端代码上传至阿里云的OSS(相当于cdn)。
步骤类型:阿里云OSS上传
内容:
创建服务端代码测试、构建、生成docker镜像节点
本文的服务端是nodejs语言,使用eggjs框架。如果使用php或者java作为后端语言,相关设置会有差异。
在fe
节点后面点击+
创建一个节点,命名为service
。
下面我们开始添加步骤,展开步骤列表,点击添加步骤
。
步骤1:在GIT上拉取服务端代码
步骤目的:拉取git上服务端代码。
步骤类型:Git
内容:
其中凭证id
需要到jenkins
的凭证管理
中添加,如下图,填如git的用户名和密码,然后自定义一个凭证id
。
步骤2:将前端的入口html放在服务端代码指定目录
在fe
节点的步骤4中,我们将前端的index.html
暂存起来,现在我们先进入服务端代码的特定目录(你想放置这个文件的目录),然后取出这个index.html
放置在这个目录下。这样你的服务端代码在用户访问的时候返回这个index.html
文件的内容即可。
步骤目的:进入服务端代码的指定目录
步骤类型:Change current directory
内容:
进入了服务端代码的app
目录,并且通过子步骤将我们暂存的index.html
放置在这个目录中。不同的服务端目录结构会有差异,请根据服务端项目结构来选择放置位置。
子步骤
在步骤2中添加一个子步骤
步骤目的:将暂存的index.html
放置在当前目录
步骤类型:Restore files previously stashed
内容:
步骤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
注意:
- 通常情况下会有多个服务器需要部署,这里作为示例只部署一台;
docker rm
是先移除服务器上旧的运行的容器;- ssh免密登录需要在两台服务器上配置密匙,这方面的资料可以自行搜索;
其它细节
清除旧的镜像
在服务器上运行远程镜像的时候每次都会存储旧的镜像在服务器中,所以有必要每次运行新镜像前清理一下旧的镜像,可以使用下面的命令来清理掉相关的镜像:
docker rmi -f `docker images | grep '[镜像的关键字]' | awk '{print $3}'` || true