使用 Drone CI 自动部署 Go 应用

本文将记录如何使用 Drone 自动部署 Go 应用。

介绍

Drone CI

官网介绍:

Automate Software Build and Testing

Drone is a self-service Continuous Delivery platform for busy development teams.

Gitea

官网介绍:

Gitea 是一个自己托管的Git服务程序。他和GitHub, Bitbucket or Gitlab等比较类似。他是从 Gogs 发展而来,不过我们已经Fork并且命名为Gitea。

Gitea的首要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。我们采用Go作为后端语言,这使我们只要生成一个可执行程序即可。并且他还支持跨平台,支持 Linux, macOS 和 Windows 以及各种架构,除了x86,amd64,还包括 ARM 和 PowerPC。

自动部署流程

  1. 项目中写入 .drone.yml 配置文件,push 到 gitea 中
  2. gitea 通过钩子函数告诉 drone
  3. drone 读取配置文件,通过 drone-runner-* 部署项目

安装

安装 drone-server 和 drone-runner-docker

这里使用 docker-compose 安装。

docker-compose 所在目录使用 docker-compose up -d 安装。

 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
version: '3'
services:
  # 容器名称
  drone-server:
    # 构建所使用的镜像
    image: drone/drone:1
    # 映射容器内80端口到宿主机的7079端口
    ports:
      - 7079:80
    # 映射容器内/data目录到宿主机的/data/drone目录
    volumes:
      - /data/drone:/data
    # 容器随docker自动启动
    restart: always
    environment:
      # Gitea 服务器地址
      - DRONE_GITEA_SERVER=http://ip:port
      # Gitea OAuth2客户端ID
      - DRONE_GITEA_CLIENT_ID=XXX
      # Gitea OAuth2客户端密钥
      - DRONE_GITEA_CLIENT_SECRET=yyy
      #- DRONE_GIT_ALWAYS_AUTH=
      # drone的共享密钥
      - DRONE_RPC_SECRET=drone_rpc_secret
      # drone的主机名
      - DRONE_SERVER_HOST=ip:port
      # 外部协议方案
      - DRONE_SERVER_PROTO=http
      # 创建管理员账户,这里对应为gitea的用户名
      - DRONE_USER_CREATE=username:admin,admin:true

  drone-runner-docker:
    image: drone/drone-runner-docker:1
    ports:
      - 7080:3000
    restart: always
    depends_on:
      - drone-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      # 用于连接到Drone服务器的协议。该值必须是http或https。
      - DRONE_RPC_PROTO=http
      # 用于连接到Drone服务器的主机名
      - DRONE_RPC_HOST=ip:port
      # Drone服务器进行身份验证的共享密钥,和上面设置一样
      - DRONE_RPC_SECRET=drone_rpc_secret
      # 限制运行程序可以执行的并发管道数。运行程序默认情况下执行2个并发管道。
      - DRONE_RUNNER_CAPACITY=2
      # docker runner 名称
      - DRONE_RUNNER_NAME=drone-runner

安装 drone-runner-exec

下载

1
2
curl -L https://github.com/drone-runners/drone-runner-exec/releases/latest/download/drone_runner_exec_linux_amd64.tar.gz | tar zx
sudo install -t /usr/local/bin drone-runner-exec

配置

配置文件为 /etc/drone-runner-exec/config ,需要手动创建并写入一下内容。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 用于连接到Drone服务器的协议。该值必须是http或https
DRONE_RPC_PROTO=http
# 用于连接到Drone服务器的主机名
DRONE_RPC_HOST=ip:port
# Drone服务器进行身份验证的共享密钥,和上面设置一样
DRONE_RPC_SECRET=drone_rpc_secret
# log 存储目录,需要自行建立
DRONE_LOG_FILE=/opt/drone/drone-runner-exec/log.txt
# 限制运行程序可以执行的并发管道数。运行程序默认情况下执行2个并发管道
# limits the number of concurrent pipelines that a runner can execute
DRONE_RUNNER_CAPACITY=2
DRONE_RUNNER_NAME=drone-runner-exec
DRONE_RUNNER_PATH=/bin:/usr/local/go/bin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin # sets the PATH variable for all pipeline steps
# 日志追踪
DRONE_TRACE=true

启动

1
2
3
drone-runner-exec service install
drone-runner-exec service start
tail /opt/drone/drone-runner-exec/log.txt

drone-runner-exec drone-runner-exec service install

read configuration /home/ubuntu/.drone-runner-exec/config

installing service drone-runner-exec

drone-runner-exec: error: cannot read configuration, try –help

项目配置文件 .drone.yml

在宿主机执行命令,编译并运行

如果项目根目录中有 .drone.yml 文件,drone 就可以读取文件中的内容,从而进行自动部署。

示例:

 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
kind: pipeline # 对象类型,有 pipeline、secret 和 signature 等类型
type: exec # 流水线类型,有 docker、kubernetes、exec、ssh 等类型
name: drone-golang-example

platform:
  os: linux
  arch: amd64

steps:
  - name: test & build
    environment:
      GOOS: linux
      GOARCH: amd64
      CGO_ENABLED: 0
    commands:
      - whoami
      - echo "==== test ===="
      - go test
      - echo "==== build ===="
      - go build -o server

  - name: copy
    commands:
      - cp -rf ./server /opt/drone-golang-example/server
      - chown ubuntu:ubuntu /opt/drone-golang-example/server
      - chmod 755 /opt/drone-golang-example/server

  - name: stop
    commands:
      - sh scripts/stop.sh

  - name: run
    commands:
      - echo "==== run ===="
      - cd /opt/drone-golang-example
      - nohup ./server 2>&1 > web.log &
      - echo "running"

  - name: notify
    commands:
      - echo "failure"
    when:
      status:
        - failure

trigger:
  branch:
    - main
  event:
    - push

其中 stop.sh 内容为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#! /bin/sh

# NR==1 第一行
# print $2 输出第二个参数
id=$(sudo lsof -i:7007|grep drone-golang-example|awk 'NR==1{print $2}')
if [ ! ${id} ]
then
    echo "项目未启动"
else
    sudo kill -9 $id
fi

在 Docker 中运行

TODO

注意

Pending

没有对应的 runner,需要哪个就安装哪个,对应 .drone.yml 中的 type,本文需要安装 ⬆️drone-runner-exec

fatal: could not read Username for 'http://ip:port': terminal prompts disabled

需要用户名等,这里发现仓库设置为了私有,改为公开,不再报此错误。

若需要使用私有仓库,参考一下这篇文章

command not found

如:

  • go: command not found
  • scripts/stop.sh: line 3: grep: command not found

在配置文件中修改配置项 DRONE_RUNNER_PATH ,需要的命令在哪个路径就加什么。

或者也可以将 .drone.yml 中的 go 改为绝对路径,比如我这里是 /usr/local/go/bin/go (不推荐)。

No such process

  • 旧:脚本使用 ps 查找进程

    第一次运行时,并没有已经运行的进程去停止,可以先把 .drone.yml 中 stop 这一步去掉。

  • 新:脚本使用 lsof 查找进程

    未启动会输出项目未启动。

某一阶段(run)一直显示 Running 不停止

。。。

Reference