持续集成工具

什么是 Drone?

Drone 是一个面向忙碌的开发团队的自助持续集成和持续交付平台。

官网地址:https://www.drone.io/

同时,Drone 是使用 Golang 语言进行编写。所有的编译、测试的流程都在 Docker 容器中执行。Drone 通过使用简单的 YAML 配置文件,就可以轻松的定义出一条流水线,并且每一个构建操作都是在一个临时的 Docker 容器中执行,能够完全控制其构建环境并保证隔离。最后,开发人员只需要在项目中引入 .drone.yml 文件,将代码推送到 Git 仓库中,即可自动化的完成编译测试发布

简单来说,Drone 其实就是一款轻量级的 Jenkins ,可以占用更少的资源,实现软件的流水线操作,并且可以轻松的和 GitlabGiteeGithub 相结合。

Drone官网

创建 OAuth2应用

由于蘑菇博客是部署在 Gitee 中的,因此本文将介绍 Drone 如何实现:代码提交到 Gitee 上,自动触发 Drone 流水线,完成项目的打包和部署

首先,打开 Gitee 上的设置页面,找到 第三方应用,然后选择创建应用

创建地址:https://gitee.com/oauth/applications

创建Gitee应用

然后填写相关的信息,需要注意的是,这里的 ip 地址,需要换成自己服务器的

  • 应用主页:服务器地址+端口号
  • 应用回调地址:服务器地址+端口号/login
  • 权限:把这四个都勾选上,否则后面登录可能会报错

配置应用信息

点击创建应用,就会得到 ClientKeyClientSecret ,需要保存好,后续在编写 docker-compose.yml 文件的时候会用到

获取ClientId

生成RPC秘钥

由于 drone serverdrone runner 通信需要使用秘钥,因此可以使用 openssl 命令生成

  1. $ openssl rand -hex 16
  2. bea26a2221fd8090ea38720fc445eca6

可以也需要保存改秘钥,在下面需要使用

编写 drone.yml 文件

首先,需要编写 dronedocker-compose 文件,用来创建 drone 容器

创建 drone.yml 文件,并修改以下的内容

  • DRONE_GITEE_CLIENT_ID:上面的 GtieeClient ID
  • DRONE_GITEE_CLIENT_SECRETGitee OAuth2 客户端密钥(上面的 Client Secret 值)
  • DRONE_RPC_SECRETDrone 的共享密钥(生成 RPC 密钥)
  • DRONE_SERVER_HOSTDrone 的主机名(改成自己的域名获得 ip+端口(注意是drome的))
  • DRONE_USER_CREATE:创建管理员账户,这里对应为 Gitee 的用户名(也就是登录的账号,不是昵称)(填错了回导致自动化部署失败)
  1. version: '3'
  2. networks:
  3. mogu:
  4. external: false
  5. services:
  6. # 容器名称
  7. drone-server:
  8. container_name: drone
  9. # 构建所使用的镜像
  10. image: drone/drone
  11. # 映射容器内80端口到宿主机的8611端口8611端口,若修改的话,那么上面Gitee上也需要进行修改
  12. ports:
  13. - 8611:80
  14. # 映射容器内/data目录到宿主机的目录
  15. volumes:
  16. - /usr/local/bin/drone:/data
  17. # 容器随docker自动启动
  18. restart: always
  19. privileged: true
  20. networks:
  21. - mogu
  22. environment:
  23. # Gitee 服务器地址如果github就把GITEE改成GITHUB和https://gitee.com改成https://github.com
  24. - DRONE_GITEE_SERVER=https://gitee.com
  25. # Gitee OAuth2客户端ID
  26. # - DRONE_GITEA_CLI(上面的Client ID值)
  27. - DRONE_GITEE_CLIENT_ID=0a334xxxxxxxxc711e40af
  28. # Gitee OAuth2客户端密钥(上面的Client Secret值)
  29. - DRONE_GITEE_CLIENT_SECRET=79173f5367xxxxx000899
  30. # drone的共享密钥(生成rpc密钥)
  31. - DRONE_RPC_SECRET=bea26a2221fd8090ea38720fc445eca6
  32. # drone的主机名(改成自己的域名获得ip+端口(注意是drome的))
  33. - DRONE_SERVER_HOST=192.168.11.1:8611
  34. # 外部协议方案根据你的域名判断是http还是https(ip加端口是http)
  35. - DRONE_SERVER_PROTO=http
  36. - DRONE_GIT_ALWAYS_AUTH=false
  37. # 创建管理员账户,这里对应为gitee的用户名(也就是登录的账号,不是昵称)(填错了回导致自动化部署失败)
  38. - DRONE_USER_CREATE=username:xxx@qq.com,admin:true
  39. docker-runner:
  40. container_name: drone-runner
  41. image: drone/drone-runner-docker
  42. restart: always
  43. privileged: true
  44. networks:
  45. - mogu
  46. depends_on:
  47. - drone-server
  48. volumes:
  49. - /var/run/docker.sock:/var/run/docker.sock
  50. - /sync/drone/agent/drone.key:/root/drone.key
  51. environment:
  52. # 用于连接到Drone服务器的协议。该值必须是http或https。(同上)
  53. - DRONE_RPC_PROTO=http
  54. # 用于连接到Drone服务器的主机名(同上)
  55. - DRONE_RPC_HOST=81.70.100.87:8611
  56. # Drone服务器进行身份验证的共享密钥,和上面设置一样(生成rpc密钥)
  57. - DRONE_RPC_SECRET=bea26a2221fd8090ea38720fc445eca6
  58. # 限制运行程序可以执行的并发管道数
  59. - DRONE_RUNNER_CAPACITY=2
  60. # docker runner 名称
  61. - DRONE_RUNNER_NAME=docker-runner
  62. - DRONE_DEBUG=true # 调试相关,部署的时候建议先打开
  63. - DRONE_LOGS_DEBUG=true # 调试相关,部署的时候建议先打开
  64. - DRONE_LOGS_TRACE=true # 调试相关,部署的时候建议先打开
  65. - TZ=Asia/Shanghai

填写完毕后,将 drone.yml 文件拷贝到服务器上,使用下面的命令运行

  1. docker-compose -f drone.yml up -d

这里需要小伙伴们提前下载好 docker-compose,如果不清楚什么是 docker-compose 的小伙伴,下面有一个简单的介绍

Docker Compose 是用来定义和运行多个Docker应用程序的工具。通过Compose,可以使用YAML文件来配置应用程序需要的所有服务,然后使用一个命令即可从YML文件配置中创建并启动所有服务

首先到 Github release中下载 docker-compose

https://github.com/docker/compose/releases

然后选择 Linux 版本下载

下载 docker-compose

把下载到的文件使用 Xftp 工具,拷贝到 /usr/local/bin/ 目录下

  1. # 重命名
  2. mv docker-compose-Linux-x86_64 docker-compose
  3. # 加入执行权限
  4. sudo chmod +x /usr/local/bin/docker-compose
  5. # 查看docker-compose版本
  6. docker-compose -v

安装完成后,再次使用上面的命令,安装 drone,安装完成后,使用 **<font style="color:rgb(233, 105, 0);">docker ps -a</font>** 即可查看到安装的 drone

运行的drone容器

下面两个运行的容器的作用分别如下:

  • drone:为 Drone 的管理提供了 Web 页面,用于管理从 Git 上获取的仓库中的流水线任务
  • drone-runner:一个单独的守护进程,会轮询 Server,获取需要执行的流水线任务,之后执行

如果正确的启动了上述的两个容器,那么你打开浏览器,输入IP:8611 可以进入到 Drone 主服务的 Web 管理界面的登录界面,

drone登录页

点击 Continue 后,即可跳转到 GiteeOAuth 授权页面,这里直接点击 同意授权

Gitee授权登录

授权通过后,在仓库的管理页面,即可看到新增了一条 WebHook 记录,当 Gitee 有新的代码提交请求后,就会通过调用下面的地址,从而让 Drone 能够启动流水线操作。

新增Webhook记录

登录成功后,即可跳转到 Drone 的主页,在这里是能够看到 Gitee 上全部的项目的

查看所有项目

找到需要构建流水线的项目,然后进入后点击 激活仓库

这里是有BUG的,如果项目是中文名称的话,进去是会 404

激活项目

然后把下面几个开关进行打开,主要是开启容器特权,以及自动取消构建

开启开关

创建一个 SpringBoot 项目

首先,在 Gitee 上创建一个私有的仓库 hello-mogu

https://gitee.com/projects/new

新建一个仓库

然后打开网站 start.spring.io 初始化一个最简单的 SpringBoot 项目

初始化一个SpringBoot项目

然后下载后解压,即可看到以下的目录

解压项目

然后使用以下命令,将该项目和刚刚创建的Gitee仓库关联上

  1. git init
  2. git commit -m "first commit"
  3. git remote add origin https://gitee.com/moxi159753/hello-mogu.git
  4. git push -u origin "master"

下面即可看到代码成功推送到 Gitee 上了

推送到Gitee

Drone 流水线命令

接下来,需要通过将 .drone.yml 文件创建到 Git 存储库的根目录来配置管道。在这个文件中,定义了每次收到 Webhook 时执行的一系列步骤。

下面这个是最简单的一个 drone 流水线,创建 .drone.yml 文件,写上下面的内容

  1. kind: pipeline # kind 属性定义了对象的种类。此示例定义了一个管道对象。
  2. type: docker # type 属性定义管道的类型。此示例定义了一个 Docker 管道,其中每个管道步骤都在 Docker 容器内执行。
  3. name: default # name 属性定义了管道的名称。您可以为您的项目定义一个或多个管道
  4. steps: # 步骤部分定义了一系列串行执行的管道步骤。如果管道中的任何步骤失败,管道将立即退出
  5. - name: greeting # name 属性定义管道步骤的名称
  6. image: alpine # image 属性定义了一个执行 shell 命令的 Docker 镜像。您可以使用来自任何 DockerHub 中的任何 Docker镜像。
  7. commands: # commands 属性将在 Docker 容器内执行的 shell 命令列表定义为容器入口点。如果任何命令返回非零退出代码,则管道步骤将失败。
  8. - echo hello
  9. - echo world

写完后,再次将该提交提交到远程仓库,然后找到刚刚创建的仓库(如果没有,先执行 SYNC 操作)

Drone中找到刚刚创建的仓库

点击仓库内,设置好配置,点击保存

修改配置并保存

然后切换到构建页面,点击创建

启动构建

创建完成后,项目就会进行流水线构建【以后可以设置代码提交,主动触发】

构建记录

点击记录详情页,可以看到打印出来的 hello world

构建详情页

更多流水线操作

例如,可以将两个步骤串连起来,第一个步骤输出 hello world、第一个输出 bonjour monde

  1. kind: pipeline
  2. type: docker
  3. name: greeting
  4. steps:
  5. - name: en
  6. image: alpine
  7. commands:
  8. - echo hello world
  9. - name: fr
  10. image: alpine
  11. commands:
  12. - echo bonjour monde

在推送代码后,就可以看到流水线已经正常输出内容了

流水线运行成功

同时,也可以定义多个管道,串联的去执行

  1. kind: pipeline
  2. type: docker
  3. name: en
  4. steps:
  5. - name: greeting
  6. image: alpine
  7. commands:
  8. - echo hello world
  9. ---
  10. kind: pipeline
  11. type: docker
  12. name: fr
  13. steps:
  14. - name: greeting
  15. image: alpine
  16. commands:
  17. - echo bonjour monde

同时,通过增加 trigger 可以设置管道触发的方式,例如,push:代码提交后触发,pull_request:代码PR后触发

  1. kind: pipeline
  2. type: docker
  3. name: en
  4. steps:
  5. - name: greeting
  6. image: alpine
  7. commands:
  8. - echo hello world
  9. trigger:
  10. event:
  11. - push
  12. - pull_request
  13. - tag
  14. - promote
  15. - rollback

下面来完整的测试一下 hello-mogu

首先,在刚刚的 SpringBoot 项目中,创建一个 Controller 文件,写上一个 hello 蘑菇的方法

hello mogu

  1. import org.springframework.web.bind.annotation.GetMapping;
  2. import org.springframework.web.bind.annotation.RestController;
  3. @RestController
  4. public class HelloMogu {
  5. @GetMapping("/hello-mogu")
  6. public String helloMogu() {
  7. return "hello-mogu";
  8. }
  9. }

然后编辑 .drone.yml 文件,编写流水线代码

  1. kind: pipeline # 定义对象类型,还有secret和signature两种类型
  2. type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
  3. name: hello-mogu # 定义流水线名称
  4. steps: # 定义流水线执行步骤,这些步骤将顺序执行
  5. - name: build-package # 流水线名称
  6. image: maven:3.8.5-openjdk-8 # 定义创建容器的Docker镜像
  7. volumes: # 将容器内目录挂载到宿主机,仓库需要开启Trusted设置
  8. - name: maven-build
  9. path: /root/hello-mogu # 将应用打包好的Jar和执行脚本挂载出来
  10. commands:
  11. - mvn clean package -DskipTests=true
  12. # 将打包后的jar包,拷贝到 /root/hello-mogu 目录
  13. - cp /drone/src/target/hello-mogu-0.0.1-SNAPSHOT.jar /root/hello-mogu
  14. volumes: # 定义流水线挂载目录,用于共享数据
  15. - name: maven-build
  16. host:
  17. path: /root/hello-mogu #jar包目录可以修改从宿主机中挂载的目录

这里使用了 build-package 的镜像进行构建,里面包含了 JavaMavne 环境。

同时,为了方便将构建好的 Jar 包挂载出来,使用了 volumes ,需要指定容器内的地址 以及 挂载到宿主机的位置

将修改后的代码推送到 Gitee 中,可以看到流水线正常运行,并且在开始下载依赖进行构建 jar

Drone 比 Jenkins 更轻量级的持续集成工具 - 图24

构建详情页

执行成功后,打开自己的服务器,在 /root/hello-mogu 目录,就可以看到刚刚打包后的 jar 包了

打包成功的jar

如果服务器有 java 环境,可以直接用下面的命令启动

  1. java -jar hello-mogu-0.0.1-SNAPSHOT.jar

下面,可以继续编写流水线,创建项目的 Dockerfile 文件,

Dockerfile的主要作用是用来构建镜像的
  1. FROM registry.cn-shenzhen.aliyuncs.com/mogu-zh/jdk:8-mogu-alpine
  2. ENV LANG C.UTF-8
  3. ENV TZ Asia/Shanghai
  4. VOLUME /tmp
  5. ADD hello-mogu-0.0.1-SNAPSHOT.jar hello-mogu-0.0.1-SNAPSHOT.jar
  6. ENTRYPOINT ["java","-Xms256m","-Xmx256m","-jar","/hello-mogu-0.0.1-SNAPSHOT.jar"]

存放位置如下所示,主要拉取了带着 jdk8 环境的镜像,然后设置启动参数

编写Dockerfile

继续编写 .drone.yml 文件,这里除了需要拷贝 jar 文件外,还需要把刚刚写的 Dockerfile 文件也拷贝到宿主机上

同时,引入 appleboy/drone-ssh 镜像,听名字就可以知道,这个命令是用来远程 SSH 连接服务器的

这里有两个变量:TEST_SERVER_IPTEST_SERVER_PASSWORD,分别是服务器的 ip密码。为了防止信息泄露,需要配置到 secret

新增秘钥

然后填写秘钥的名称和值,保存即可

创建秘钥

配置完成后,一共包含以下两个值

创建成功

完整的流水线代码如下:

  1. kind: pipeline # 定义对象类型,还有secret和signature两种类型
  2. type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
  3. name: hello-mogu # 定义流水线名称
  4. steps: # 定义流水线执行步骤,这些步骤将顺序执行
  5. - name: build-package # 流水线名称
  6. image: maven:3.8.5-openjdk-8 # 定义创建容器的Docker镜像
  7. volumes: # 将容器内目录挂载到宿主机,仓库需要开启Trusted设置
  8. - name: maven-build
  9. path: /root/hello-mogu # 将应用打包好的Jar和执行脚本挂载出来
  10. commands:
  11. - mvn clean package -DskipTests=true
  12. # 将打包后的jar包,拷贝到挂载目录
  13. - cp /drone/src/target/hello-mogu-0.0.1-SNAPSHOT.jar /root/hello-mogu
  14. # 将Dockerfile拷贝到挂载目录
  15. - cp /drone/src/target/classes/Dockerfile /root/hello-mogu
  16. - name: ssh
  17. image: appleboy/drone-ssh
  18. settings:
  19. # 你服务器ip地址
  20. host:
  21. from_secret: TEST_SERVER_IP
  22. # 服务器账号
  23. username: root
  24. # 密码登入写法
  25. password:
  26. from_secret: TEST_SERVER_PASSWORD
  27. port: 22
  28. script:
  29. - cd /root/hello-mogu
  30. - ls
  31. - docker build -t hello-mogu:latest .
  32. - docker run -p 8080:8080 -d hello-mogu:latest
  33. volumes: # 定义流水线挂载目录,用于共享数据
  34. - name: maven-build
  35. host:
  36. path: /root/hello-mogu #jar包目录可以修改从宿主机中挂载的目录

核心操作就是:在 jar 打包完成后,会通过 ssh 进入到服务器中,通过 Dockerfile 构建 hello-mogu 镜像,同时使用 **<font style="color:rgb(233, 105, 0);">docker run</font>** 启动镜像,完成最简单的一个流水线工作,以下是流水线运行成功的截图:

构建成功

下面,去服务器中,使用 docker images 命令,即可查看到制作完成的镜像了

查看容器

通过使用 docker ps -a ,可以看到目前 hello-mogu 容器正在运行

查看运行的容器

最后,访问服务器:http://81.70.100.87:8080/hello-mogu,久违的 hello-mogu 终于出现了

hello mogu

同时,Drone 还提供了很多插件,可以打开 https://plugins.drone.io/ 进行查看

drone插件

在这里,可以下载别人做好的插件,例如在构建成功后,发送邮件通知,这里用到了 Email 插件

Email插件

或者使用 Drone Cache 插件,将中间结果缓存到云存储

Drone缓存插件