目前的构建方案是:Github + Drone + Docker ( docker安装 )

先来看看修改前后服务器内存占用对比

使用Jenkins时:

image.png

这是停掉Jenkins,启用Drone时:

image.png

可以看到内存占用直接下降了一半,感觉轻量到可以飞起来~

体积上更是两个维度:

image.png

如果要说Drone有什么缺点的话,就是官方文档过于简单吧,有什么问题也比较难找到文章,导致折腾了不少时间。

0. 配置Github

这是使用Github作为代码托管的前置工作,首先登陆你的github账户,在右上角点击个人头像,选择Setting,选择Developer settings,选择OAuth Application,选择新建一个application:

image.png
image.png

创建成功以后,拿到Client IDClient Secret,拿小本本记下来。

  1. 这里需要注意的是 callback URL 需要填写你的Drone的登录地址,具体为drone主页链接后面加上/login

1. 安装Drone

使用docker安装drone,drone需要创建两个容器,一个提供视图界面的webService端,另一个是执行任务的runner端,这里先安装web端。

注:运行时去掉#号后面的说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
docker run \
--volume=/var/drone:/data \ # 备注:1
--env=DRONE_GITHUB_CLIENT_ID= \ # 备注:2
--env=DRONE_GITHUB_CLIENT_SECRET= \ # 备注:2
--env=DRONE_RPC_SECRET= \ # 备注:2
--env=DRONE_SERVER_HOST= xxx.com \ #备注:3
--env=DRONE_SERVER_PROTO=http \ #备注:4
--env=DRONE_USER_CREATE=username:name,admin:true \ #备注:5
--publish=10086:80 \ #备注:6
--publish=10087:443 \ #备注:6
--restart=always \
--detach=true \
--name=drone \
drone/drone:latest
  1. drone与宿主机的目录映射,其中可将/var/drone换成你宿主机自定义的目录
  2. 填写上一步的Client IDClient Secret,RPC_SECRET和Client Secret一致
  3. 你的drone域名,没有则填IP:端口
  4. 没特殊情况推荐设置http
  5. 设置admin账户(必须),将name改成你的github账户名称
  6. 映射主机的端口号(我这里占用宿主机10086端口,使用drone容器中的80端口),对外的10086端口设置为你自定义端口,记得确认已配置白名单

1.1 配置nginx

贴一份nginx的配置,这里主要映射了目录到宿主机/data/nginx的位置,方便修改配置,提前配置好上一步用到的域名,如果需要的话。

1
2
3
4
5
6
7
docker run -d \
-v /data/nginx/nginx.conf:/etc/nginx/nginx.conf \
-v /data/nginx/cert:/etc/nginx/cert \
-v /data/docker_home:/home \
--net host \
--name nginx \
nginx

2. 安装runner

1
2
3
4
5
6
7
8
9
10
11
12
docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-e DRONE_RPC_PROTO=http \
-e DRONE_RPC_HOST=xxx.com \ # 备注:1
-e DRONE_RPC_SECRET=xxx \ # 备注:2
-e DRONE_RUNNER_CAPACITY=2 \
-e DRONE_RUNNER_NAME=runner\
-e TZ="Asia/GuangZhou" \
-p 10088:3000 \
--restart always \
--name drone-runner \
drone/drone-runner-docker:latest
  1. 填写drone域名,或IP:端口
  2. 同上一步的RPC_SECRET也就是Client Secret

3. 登录

打开配置好的网址,登录时会调起Github登录,登录你的Github账户即可。

image.png

点击右上角可同步你的仓库,会看到你所有的项目

点进你需要进行管理的项目(可以往github创建一个仓库测试),点击激活即可:

image.png

激活仓库之后可以进行一些配置,基本按如下即可,Trusted选项为管理员才可设置:
image.png

激活仓库时Drone会往仓库发送一条activie通知,此时对应仓库会设置进一个当前的webhook记录,不用手动去配置,非常方便。

4. 自动触发构建

接下来往测试仓库提交一条commit记录测试下

  1. 直接前往Github创建一个仓库d_test,进入Drone,点击右上角同步仓库,搜索d_test,点击Active按钮激活。

  2. d_test仓库根目录创建新文件 .drone.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    kind: pipeline
    type: docker
    name: default

    clone:
    disable: true

    steps:
    - name: 编译步骤
    image: alpine
    commands:
    - echo hello drone

    简单解释下上面的配置,首先这个文件目录与名称是可以自定义配置的,在Drone项目管理的Setting里:

image.png

配置文件注意缩进,type: docker是我们后面最主要使用的构建方式,你或许已经看出来了step里可以配置多个步骤,每个步骤都会拉取一份docker镜像使用一个临时的容器来运行,结束后立即销毁。

clone哪一行配置是将drone默认的clone步骤关闭了,由于网络问题clone仓库代码会比较耗时,后面会详细讲解实例如何自己编写一个clone操作。

  1. 回到Drone的项目管理,看到构建已经自动触发了:

image.png

image.png

而这时候这个项目也成为了活跃项目可以被筛选

image.png

至此Drone已经顺利跑起来了,美好而简单,一切准备就绪。

简单画了一下当前的架构图:

image.png

编写yml配置文件

一份基础的.drone.yml配置可能是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
kind: pipeline
type: docker
name: 部署Web项目

clone:
disable: true

steps:

- name: docker-clone
image: alpine/git

- name: docker-move
image: alpine

- name: docker-deploy
image: appleboy/drone-ssh

trigger:
branch:
- publish
event:
- push

volumes:
- name: cache
host:
path: /data/cache

可以看到根级的clone选项被我设置了disable: true,这表明无需clone代码,不设置的话drone默认会有一个clone的步骤。

根级steps则具体描述了整个部署过程,它可以是分阶段的,通过-来创建,这里我们整个部署过程都基于docker,在每个步骤下我们必须描述当前会基于哪个镜像操作,然后进行到该步骤时drone会创建一个临时的docker容器,这种容器插件的理念会贯穿在我们整个构建过程中。

多个步骤下,创建的容器实际都是独立的,但它们应该都挂载映射了同一个目录 /drone/src,所有容器的操作都是在这个目录下进行的,假设在步骤1中创建的容器A,创建了一个文件,然后在步骤2中创建容器B,对这个文件进行操作,这就是我部署所有步骤的核心。而具体操作什么,则以步骤2中的容器所依赖的镜像来决定(比如这个文件是Java,那么容器B就应该拉取的是java的docker镜像来操作,很好理解吧)。

根级的trigger我则简单配置了对分支的过滤,意思是只有当提交的代码是publish分支下的,才会执行部署操作。

下面我以一个实例来演示我如何部署。

拉取代码

部署的第一步,是获取目标代码,这个步骤可以使用alpine/git这个镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
steps:
- name: docker-clone
pull: if-not-exists
image: alpine/git
environment:
warehouse_name: 仓库名
publish_branch: publish
volumes:
- name: sshkeys
path: /root/.ssh
commands:
- echo $publish_branch
- echo $DRONE_GIT_SSH_URL
- chmod -R 600 /root/.ssh/
- ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
- git clone -b $publish_branch --depth=1 $DRONE_GIT_SSH_URL
- cd $warehouse_name
- mv -f ./* /drone/src

volumes:
- name: sshkeys
host:
path: /root/.ssh

配置ssh (在宿主机环境, 已配置则忽略) :

1
ssh-keygen -t rsa -C "your_email@example.com"
1
2
3
cd /root/.ssh/

cat id_rsa.pub

在这一步,前置步骤需要宿主机和Github配置好SSH的公钥私钥,这里主要是让容器内的环境可以使用宿主的sshKey,然后以最低深度clone仓库下publish分支的代码,其中environment是为该环境下注入全局变量。

最后我将clone下来的代码全部移到默认根目录,方便接下来操作。

执行部署

这一步比较灵活,通用的步骤是以ssh连接宿主机,这样进入宿主机之后就可以执行一些docker操作。

1
2
3
4
5
6
7
8
9
10
11
12
- name: link-to-ssh
pull: if-not-exists
image: appleboy/drone-ssh
settings:
PASSWORD:
from_secret: PASSWORD
host: xx.xx.xx.xx
username: root
password: PASSWORD
port: 22
script:
- echo hello world

这一步由于涉及到服务器私密信息,不想暴露在配置文件中,于是需要到Drone的对应项目管理下创建一个Secret

image.png

然后通过from_secret即可调用到。

在线编译前端示例

drone会拉取node镜像,然后执行代码编译。

1
2
3
4
5
6
7
8
- name: build-front
pull: if-not-exists
image: node
settings:
mirror: https://docker.mirrors.ustc.edu.cn
commands:
- yarn
- yarn build

编译完成后可以通过volumes将编译后文件放到宿主机。

由于我个人服务器资源不高,在线编译速度慢,所以我其实是在本地进行打包编译,然后用脚本将打包后的dist目录压缩到publish分支再提交,而drone只需要执行解压文件转移文件即可。这部分与drone没有太大关系,所以暂不展开细说。

尚未解决的问题

目前有一个问题是项目仓库必须是公开的,一旦设为私有库webhook就无法正确请求到drone了,调试很久也不知原因,这在我之前使用Jenkins的时候并无此问题,所以判断应该是drone本身有bug,但如果对于企业项目的话代码不会托管在Github这种第三方平台,都是内部自己的仓库(如gitlab等),所以项目都没必要设为私有。

轻量代码仓库的解决方案有GogsGitea等,但我实在折腾不动了,于是把自己的项目改造了一番,涉及账号等私密信息的都不存放在代码里了。

后记: 一个坑点

在Github配置Apps的时候,关注下这个地方的设置,有个token过期的机制最好退出一下,不然8小时后webhook就会失效,只能重新登录drone才会正常。

image.png

补充: 码云Gitee

drone从v2.7.2版本开始支持gitee 官网文档,部署方式和Github差不多,可以直接参考官网文档来配置,流程就是在Gitee创建第三方应用,获取Id和Key,记录下来,然后参照上面的流程即可。

如果配置Admin账户那一步不清楚用户名的话,点击码云的个人中心,看浏览器URL链接,/后面的就是你的用户名。

有些需要注意的地方也说明一下:

0. 仓库404问题

这个问题只在码云会遇到,由于码云的新建仓库逻辑是把仓库名称和链接分开的,所以一定要保证两者一致,采用驼峰写法它会”自作聪明”地给你把链接拆成带’-‘的形式,这样drone识别仓库就会404了。

image.png

1. SSH算法问题

码云SSh不再能使用ras算法了,所以生成公钥需要使用 ssh-keygen -t ed25519 -C "yourName@xxxx.com" 这种key才可以使用。记得上面的加入主机列表也要改成 - ssh-keyscan -t ed25519 gitee.com >> ~/.ssh/known_hosts