最近公司的项目准备部署 Jenkins CI/CD,正好我在开发自己的博客主题,就用自己的博客来试试水。

目标是:每当我提交代码到 master 分支后,jenkins 会自动获取代码,编译,测试,通过后把代码自动部署到服务器上。

然后我就可以过上 写代码 -> git push -> 泡茶 -> 享用新功能 的幸福生活。

部署 Jenkins

我的系统环境是 ubunut 18.04.3,直接跑官方 Docker [jenkinsci/blueocean](https://hub.docker.com/r/jenkinsci/blueocean)

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

由于设置了 -d detach ,jenkins 会在后台运行,接下来直接访问 服务器地址:8080 就好啦。

解锁 Jenkins

解锁 Jenkins

打开后发现是一个寻宝任务,查看控制台 log 或者查看 /var/jenkins_home/secrets/initialAdminPassword 文件,获取 admin 密码。

# 查看 console log
docker logs <docker-container-name>

# 查看文件
docker exec -it <docker-container-name> bash
# 进入容器后,不要切换用户,该文件是 root 用户所有
cat /var/jenkins_home/secrets/initialAdminPassword

愉快的 Cmd+C Cmd+V :)

安装过程很极客很专业,极度舒适,真香。

安装完创建用户就可以进入 Jenkins dashboard 了,这 UI… 真…真臭。

为了提升 Jenkins 的用户体验,Blue Ocean 诞生了。点击左边的 Blue Ocean 按钮就可以使界面焕然一新,真香。

如果左边栏里没有 Blue Ocean 入口,就说明没有安装 Blue Ocean 插件,点击系统管理下的插件管理安装 Blue Ocean 即可。

准备工作

在创建流水线之前,有一些准备工作要做:

  • 写 deploy 脚本
  • 把 docker 容器 root 用户的公钥上传到博客服务器,因为 deploy 脚本需要免密 ssh 连接博客服务器来更新代码

deploy 很简单,就几行:

#!/bin/sh
ssh 用户名@服务器地址 <<EOF
cd /var/www/html/wp-content/themes/Animus
git pull
exit
EOF

上传公钥也很简单:

# docker 容器
# 创建密钥
ssh-keygen -t rsa
# 添加博客服务器到 known_hosts
ssh-keyscan 服务器地址 >> ~/.ssh/known_hosts
# 复制公钥
cat ~/.ssh/id_rsa.pub

# 博客服务器
# 把公钥添加到 authorized_keys
vi ~/.ssh/authorized_keys

这样 docker 容器就可以 ssh 免密连接博客服务器了。

创建流水线 (pipeline)

在部署项目的时候,一般都要经过环境构建 (Build)、测试 (Test) 和部署 (Deploy) 这 3 步,过程线性同步,就像一条流水线一样,环境构建好了才能运行测试脚步,测试通过了才能部署到生产环境。

在创建流水线之前,需要先创建一个叫 Jenkinsfile 的文件,这个文件定义了整条流水线的步骤。当然,名称是可以自己设置的,在 jenkins 项目配置里。

例如我现在的简易 Jenkinsfile:

pipeline {
    agent none
    stages {
        stage('Build') {
            agent { docker 'node:12.16.1-alpine3.11' }
            steps {
                sh 'npm install'
                sh 'npm run sass'
            }
        }
        stage('Deploy') {
            agent any
            steps {
                sh './jenkins/scripts/deploy.sh'
            }
        }
    }
}

其中 agent 定义了流水线在哪种 Jenkins 环境运行,这里是为不同阶段定义了不同的运行环境 Build 阶段运行在一个新的 docker 里,docker 镜像为 node:12.16.1-alpine3.11,Deploy 阶段运行在当前环境下,就是 Jenkins 的 docker 容器里,因为这里可以 ssh 免密登录服务器。

stages 定义了流水线各个阶段的指令,其中 steps 定义了需要被执行的每一步。这里在 Build 阶段执行 npm 模块安装和 sass 的编译,Deploy 阶段执行 deploy 脚本。(暂时只编译个 sass 玩一下,熟悉下游戏规则,后面再加其它好玩的)

把 Jenkinsfile 上传到项目根目录。点击 Blue Ocean 的创建流水线按钮,按要求填。

完成后就会在 Blue Ocean 的主界面看到刚刚建好的流水线,看到它在自动跑第一次构建:

正在构建中

正在构建中

部署成功!

部署成功!

大成功~最新代码已经被 Jenkins 自动部署到服务器上了。

自动化流水线

用 Blue Ocean 创建的流水线其实是多分支流水线 (Multibranch Pipeline),是 Jenkins 可构建项目的一种。多分支流水线在创建好以后会扫描配置里 Github 仓库的所有分支,把有 Jenkinsfile 的分支都执行一次构建。

但是,现在只能手动触发流水线,想要实现 Push 后 Jenkins 自动扫描一次仓库就需要 Github Webhook 的参与。

Github Webhook 的配置在仓库 -> settings -> webhook 里,点击 Add webhook 按钮。填好 Payload URL,选择 Just the push event,保存设置。

配置 Github webhook

配置 Github webhook

每次 git push 后,Github 会发送 POST 请求到目标地址,Jenkins 接收到请求后会扫描一次仓库,然后执行构建。相关日志可以在 Jenkins 多分支流水线事件里看到。

小结

总体来说,功能实现了,还很拿衣捂,以后在此基础上慢慢完善吧。