如何在CoreOS与Docker上利用Drone.io执行持续集成测试

内容简介

Want a minimal setup continuous integration solution? Who wouldn’t! 如何才能轻松设置一套持续集成解决方案?答案很简单:Drone.io利用Docker容器运行测试任务,同时可与 GitHub、GitLab (自我托管且基于服务) 以及Bitbucket实现协作。

Drone由Go语言编写而成且可利用Docker方案。其能够运行在容器之内,且几乎无需经过太多配置修改。

持续集成是一类开发实践,具体为频繁向代码库提交内容,同时在过程中实现构建与测试。这意味着新代码将(在理想状态下)快速且轻松地被集成至我们的现有代码库当中。由于持续集成要求大家频繁对代码进行构建与测试,因此以自动化方式执行这两项任务能够极大提升开发速度——正是为此而生。

Drone能够自动从托管Git库中提取代码,而后运行我们所定义的脚本。大家可以运行任意测试套件,并使其通过邮件或者README文件对特定指标进行报告。Drone提供的Docker集成能力意味着其可以支持多种语言类型,包括PHP、Node、Ruby、Go以及Python等等。每项测试都将根据Docker公共注册表中的指定镜像生成一套新容器。这意味着随着镜像数量的不断增加,其对于语言及开发堆栈的支持能力也将得到扩展。大家甚至可以亲自动手构建镜像以适应自己的特定应用!

在今天的教程中,我们将探讨如何对Drone.io进行容器化,从而保证其可在精简化Linux发行版CoreOS当中得以运行。

先决条件

  • 至少向账户中添加一条SSH密钥
  • 单一CoreOS Beta Droplet(512 MB内存即可)

如果各位此前从未使用过这套操作系统,建议大家阅读CoreOS介绍一文。

If you are unsure of how to configure CoreOS using a

cloud-config file, you can find more information, plus a sample config file,如果大家不了解如何利用cloud-config文件进行CoreOS配置,则可在此处获取更多信息外加一个示例配置文件。我们将在下面的教程中使用该示例文件。

第一步——准备GitHub

在开始之前,我们需要通过oAuth对GitHub账户进行访问。我们还将在后面的Drone容器设置步骤中生成两条令牌。

我们需要利用自己的GitHub账户生成这些值。点击此处以访问GitHub上的对应设定页面,名为“Applications”。

点击右上角的“Register new application”按钮,弹出的新表单将如下所示:

 

tu120161216144814

 

在这里添加我们的应用名称。此处的主页URL应为http://YOUR_DROPLET_IP:8080/。完成后,添加应用程序描述。

注意:确保将验证回调URL设定为http://YOUR_DROPLET_IP:8080/api/auth/github.co,从而正确完成验证!

设置完成后,点击“Register application”以进入新应用的信息页面。

在这里大家需要获取两条信息,其一为Client ID,其二Client Secret。(顾名思义,Client Secret需要保密,绝不要与他人分享其内容!)

这些令牌将被用于验证我们自己的Drone应用,从而将webhooks添加至我们通过仪表面板向Drone中加入的任何GitHub库当中。这些webhooks将在每次感知到指向GitHub的新提交操作时被触发,而Drone则会克隆这些新变更并运行构建操作。

请注意这些令牌,我们在下面的部分中将要用到。

第二步——编写Dockerfile

在CoreOS Droplet配置完成之后,通过SSH进行接入:

ssh -A core@YOUR_DROPLET_IP

创建一个名为droneio的新目录:

mkdir droneio
cd droneio

由于CoreOS的root文件系统拥有只读属性,因此我们无法直接安装Drone.io。我们需要首先利用Docker对其进行容器化。与Ubuntu系统的使用方式一样,我们将设置一个容纳有相关指令的Dockerfile,并利用它对Drone.io进行安装。

在本示例中,我们将使用基于终端的文本编辑器vim——其同时也是CoreOS上的默认文本编辑器。

现在利用以下命令打开vim并创建我们的Dockerfile:

vim Dockerfile

这条命令会打开vim并在当前目录中创建一个名为Dockerfile的新文件。

现在进入插入模式,即按下i键。按下后,终端左下角会提示:

    -- INSERT --. Now you can type or paste in the Dockerfile contents.

现在Dockerfil已经创建完成,而且每一行都拥有对应的注释。大家可以直接复制该文件:

# Pull from base Ubuntu image
FROM ubuntu

# Do system updates and install dependencies
RUN apt-get update
RUN apt-get -y upgrade
RUN sudo apt-get -y install git wget
RUN apt-get clean

# Download Drone.io
RUN wget http://downloads.drone.io/master/drone.deb
RUN dpkg -i drone.deb

# Expose the Drone.io port
EXPOSE 8080

ENV DRONE_SERVER_PORT 0.0.0.0:8080
ENV DRONE_DATABASE_DATASOURCE /var/lib/drone/drone.sqlite

# Define our GitHub oAuth keys below
ENV DRONE_GITHUB_CLIENT <CLIENT_TOKEN_HERE>
ENV DRONE_GITHUB_SECRET <CLIENT_SECRET_HERE>

# The command we’ll be running when the Container starts
CMD /usr/local/bin/droned

将其中的<CLIENT_TOKEN_HERE>与<CLIENT_SECRET_HERE>替换为我们之前提到过的令牌。

输入以下指令以保存做出的变更。其中w用于告知vim将该文本写入至文件,而q则表示退出vim。

:wq

下面来看Dockerfile中各命令的具体作用:

  • FROM – 我们将用于容器的镜像
  • RUN – 在构建过程中于容器内执行一条命令
  • EXPOSE – 允许外部人员通过特定端口访问该容器
  • CMD – 此命令会在容器启动时加以执行
  • ENV – 在容器内设定一条环境变量值并用于Drone配置

欲了解更多与Dockerfile相关的设置方案,大家可以参阅Docker官方说明文档。

现在我们已经可以利用以下命令进行镜像构建了:

docker build -t my_drone .

整个过程可能需要几分钟。在构建成功后,我们即可利用这套新镜像运行容器系统。

第二步——启动Drone容器

Drone.io需要存储部分信息,因此我们将使用一个SQLite数据库文件。现在创建一个空文件:

touch drone.sqlite

此文件将在容器启动并运行之后接收来自Drone的数据。

Drone的启动方式非常简单,但我们还需要采取其它几个步骤以确保Drone能够访问我们的主机Docker服务器。最便捷的实现办法就是使用一个分卷,将该主机socket文件与容器socket文件的所处位置进行绑定。具体容器启动命令如下:

docker run -d --name="drone-ci" \
-p 8080:8080 \
-v /var/lib/drone/ \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /home/core/droneio/drone.sqlite:/var/lib/drone/drone.sqlite \
my_drone

下面对其内容进行逐一解释:

  • docker run -d –name=”drone-ci” – 在这部分命令中,我们要求Docker在后台运行此容器,这样我们就不必担心在断开SSH会话后其会被关闭了。我们还为其选择了一个友好的名称,drone-ci,这样就可以利用docker命令进行后续管理了。
  • -p 8080:8080 – 这里我们将主机的端口8080与容器的同一端口进行绑定。如此一来,我们能够在容器运行网络之外对Drone接口进行访问。
  • -v /var/lib/drone – 这部分用于设置一个负责容器内存储的分卷。
  • -v /var/run/docker.sock:/var/run/docker.sock – 通过这种方式,我们将允许Drone.io容器控制主机的Docker系统。我们将该容器的Docker UNIX socket文件位置与实际主机的Docker UNIX socket文件位置进行绑定。换言之,我们要求Drone使用主机CoreOS之上的Docker文件,而非Drone所运行之容器内的文件。之所以这样做,是因为该主机已经安装了Docker,而容器却还没有(意味着Docker容器没有运行嵌套安装的Docker)。
  • -v /home/core/droneio/drone.sqlite:/var/lib/drone/drone.sqlite \ – 将之前创建的空存储文件绑定至数据库内的容器,从而保证全部数据都被保存于其中。此文件存在于容器之外,这样我们就可以利用它实现数据恢复,或者以外部方式对该数据库进行修改。
  • my_drone – 我们利用此前构建完成的镜像来运行这套容器。

运行上述命令,一旦出现错误,请认真检查是否创建了该空数据库文件,且全部相关路径都得到正确输入。

为了确保容器处于运行状态,我们可以进行快速状态检查:

docker ps

输出结果应如下所示:

CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                             NAMES
6eddddd09900        my_drone:latest    "/bin/sh -c '/usr/lo   1 seconds ago       Up 1 seconds        0.0.0.0:8080-&gt;8080/tcp            drone-ci

我的容器无法正常启动!

如果大家运行docker ps但却得不到任何返回结果,请首先确保输入内容全部正确。另外,大家也可以尝试不换行的命令运行方式。另外,确保我们在正确的目录中创建了drone.sqlite空文件。

为了重构容器并再次尝试,我们需要从Docker当中移除故障容器; 否则,其可能引发容器重复命名错误。

利用docker rm drone-ci移除旧容器(注意,我们使用的为此前在命令中包含的容器名称)。随后,尝试运行上一节中提到的“长度惊人”的docker run命令。

如果容器正常启动,但大家无法访问其安装页面,那么可尝试进行重启。使用docker stop drone-ci命令停止容器运行。或者使用docker kill drone-ci命令更为激进地关闭其进程。之后,利用docker start drone-ci命令进行重启。

如果大家需要查阅容器日志信息,可以使用Docker的log命令:

docker logs drone-ci.

第三步——设置Drone

现在我们已经可以利用初始账户设置Drone了。打开网络浏览器并导航至http://YOUR_DROPLET_IP:8080/login。登录界面如下所示:

 

tu220161216144833

 

我们只看到了GitHub,因为它是我们惟一在Dockerfile中设定过的服务。

现在点击GitHub按钮,而后是Authorize application按钮以启动登录与同步流程。

 

tu320161216144847

 

这时我们看到的为Drone主仪表板,大家可以发现GitHub账户中的最近三套库,点击“BROWSE ALL”即可释放完整列表。如果所有库都未能正常显示,请直接点击右上方的“SYNC”。

仪表板的其它功能亦易于上手,大家可以随意尝试。

下面我们需要允许其访问自己的各Git库源。

第四步——从GitHub处获取builds

找到需要添加至Drone CI的库名称并选定。这步操作将激活Drone并向库内添加webhooks。

激活之后,大家会看到空白的库状态页面:

 

tu420161216144855

 

我们可以利用右上方的按钮了解更多高级设置选项。

.drone.yml文件

我们需要在库内建立一个名为.drone.yml的新文件。此文件用于指挥Drone并告知其如何构建并测试GitHub库中的代码。我们可以利用以下方式轻松测试Drone是否设置妥当。

image: dockerfile/nginx
script:
- echo hello world
  • image负责定义我们作为提取源的基础镜像(该镜像可来自公共Docker注册表、专有注册表或者本地构建)。在本示例中,我们使用Nginx镜像。
  • script负责定义Drone需要执行的命令以及执行顺序。大家可以在这里定义多条脚本命令。
  • <具体命令>另起一行(注意进行标签排列)。

此脚本会echo“hello world”以验证Drone处于工作状态。其不会对代码进行任何实际测试。

在实际构建与测试场景当中,大家可能希望让Drone使用Docker镜像以配合现有生产环境,同时需要上述脚本测试库中的代码。

现在将.drone.yml文件提交至库中。大家进行的全部提交操作(包含任何文件)都将触发库中的webhook Drone。到这里,Drone应该已经开始从基础镜像中提取任务并根据脚本运行命令了。

Drone将检测这一新的提交内容,克隆任何与代码相关的变更,而后根据.drone.yml文件中的定义指令进行操作。其将在页面底部显示通知,提醒大家该build正在运行——点击即可查看build状态页面。

 

tu520161216144905

 

整个构建工作大概需要几分钟时间,因为Drone需要从Docker公共注册表内获取镜像。

当构建流程完成后,大家可以点击对应提交以查看更多细节信息。具体内容如下所示:

$ git clone --depth=50 --recursive --branch=master git://github.com/captainshar/dronetest.git /var/cache/drone/src/github.com/captainshar/dronetest
$ git checkout -qf 9908588ae4e4abcba8afb5029baad5c49a835ba4
$ echo hello world
hello world
$ exit 0

大家可能还会看到几条与Perl相关的警示信息——忽略即可。

完成了以上几个步骤后,现在大家已经拥有自己的个人Drone.io工作程序了,其能够构建并测试基于几乎任何语言的项目!

Drone还支持Bithucket与GitLab,而利用oAuth进行的设置流程与GitHub基本一致。大家可能需要编辑Dockerfile并利用正确的环境变更对该容器进行重构:

DRONE_BITBUCKET_CLIENT
DRONE_BITBUCKET_SECRET
DRONE_GITLAB_URL
...

下一步

现在大家已经拥有了能够运行builds的Drone,并可以修改.drone.yml文件以实现更多高级测试。

举例来说,如果大家希望利用Karma或者Mocha等测试架构对一款Node应用进行测试,则可将image部分变更为官方node image,并将script部分变更为执行npm并运行测试。具体内容请参阅Docker注册表以了解适合自己应用需求的具体作法。

如果大家希望玩点更高深的,也可以参阅Drone Wall了解如何为全部build状态建立一套统一的显示面板。

祝各位的Drone之旅一路顺风!

英文原文:How To Perform Continuous Integration Testing with Drone.io on CoreOS and Docker By Aaron Shea

分享到:更多 ()