GitHub 低代码
发布于 

Drone(轻量持续部署服务)

概述: 把重复的手动部署工作, 利用Drone工具自动处理整套部署步骤. 「自动执行.sh脚本」

执行的步骤大概如:

  • 场景1:
    • 打包: 拉取代码 –> 更新依赖(npm i) –> 构建项目(build)
    • 部署: 删除旧的资源包 –> 替换新构建的资源包
  • 场景2(Docker):
    • 打包: 拉取代码 –> 更新依赖(npm i) –> 构建项目(build) –> 打包镜像(DockerFile) –> 推送到镜像仓库
    • 部署: SSH连接到服务器 –> 拉取新镜像 –> 停止和移除旧容器 —> 启动新容器

Drone安装

Drone由 Server(服务器) 和 Runner(执行器) 组成

  • Server
    • 连接到代码仓库 (GitHub、GitLab、Gogs、Gitea、Gitee、…)
    • 提供了Web管理界面
    • 管理 Runner
  • Runner(执行持续部署操作的服务)
    • 执行时会轮询 Server 来确定执行的操作

准备工作

在Gitea上为Drone创建OAuth认证登陆

  1. 输入信息, 点击保存
  2. 记录生产的信息
    1. 客户端ID: e5c409df-36be-4cb6-aa25-151325754c3f
    2. 客户端密钥: x8Uu2gHyjjhJbbLf2VltvwfMFF3mVTLk0xiHdE9bJjy3

生成 Drone Server 和Drone Runner 通信密钥 「共享密钥」

1
2
openssl rand -hex 16
# 输出如: efb695f7109af80ff7582768dd07c3ae

通过docker-compose安装Drone

  • 配置 docker-compose 文件
1
2
3
4
5
6
# 创建drone的专属目录
mkdir /home/git/drone
cd /home/git/drone

# 写入配置
vi docker-compose.yml
  • docker-compose.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
version: '3'
services:
# 容器名称
fan-drone-server:
# 构建所使用的镜像
image: drone/drone:2
# 映射容器内80端口到宿主机的3222端口
ports:
- 3222:80
# 映射容器内/data目录到宿主机的/home/git/drone目录
volumes:
- ./data:/data
# 容器随docker自动启动
restart: always
environment:
# Gitea 服务器地址
- DRONE_GITEA_SERVER=http://124.222.237.29:3333
# Gitea OAuth2客户端ID
- DRONE_GITEA_CLIENT_ID=e5c409df-36be-4cb6-aa25-151325754c3f
# Gitea OAuth2客户端密钥
- DRONE_GITEA_CLIENT_SECRET=x8Uu2gHyjjhJbbLf2VltvwfMFF3mVTLk0xiHdE9bJjy3
# drone的共享密钥
- DRONE_RPC_SECRET=efb695f7109af80ff7582768dd07c3ae
# Drone 的主机名
- DRONE_SERVER_HOST=124.222.237.29:3222
# 外部协议方案
- DRONE_SERVER_PROTO=http
# username 为创建OAuth2应用的Gitea管理员用户 , 否则不具有管理员权限。
# 非管理员用户缺少选择 (Trusted、Auto cancel pushes、Auto cancel running)
- DRONE_USER_CREATE=username:git,admin:true
# 拉取代码的时候开启认证
- DRONE_GIT_ALWAYS_AUTH=true

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

激活仓库

访问 124.222.237.29:3222 会直接跳转Gitea认证页面

此处省略注册步骤~~~

进入面版看到gitea中的test1项目, 没有的则点击SYNC同步项目

点击test1项目, 进去setting选项并点击激活按钮激活项目

简单测试, 分享常见错误

在test1测试项目, 建立 .drone.yml 文件, 并写入以下内容进行测试

PS: test1项目 是由vite脚手架, 简单构建出来的ts-react项目

1
2
3
4
5
6
7
8
9
10
# .drone.yml 文件
kind: pipeline # 定义一个管道
type: docker # 类型
name: test # 名称
steps: # 管道的执行步骤
- name: test # 步骤名称
image: node:latest # 步骤使用的镜像
commands: # 当前步骤执行的命令
- echo 测试drone # 测试输出
- pwd # 查看执行目录

正确例子

  • 输出1: 测试drone drone正常执行
  • 输出2: drone执行的绝对路径为 /drone/src

错误1: 用户非Gitea管理员用户

错误效果

正确效果

解决

确保Gitea用户是管理员用户

确保docker-compose配置中git用户是Gitea的管理员用户

  • DRONE_USER_CREATE=username:git,admin:true

PS: 修改配置之后记得重启drone服务

错误2: 不受信任的仓库 untrusted repositories cannot mount host volumes

错误效果

解决

确保Trusted选项已勾选

Settings –> Project Settings –> Trusted

错误3: 拉取代码失败 Fatal: could not read Username for

错误效果

解决

  • 官方解答
  • 方向1:
    • 开启私有仓库选项 「Settings –> Project Visibility –> Public改成Private」
    • 开启认证, docker-compose.yml 中 DRONE_GIT_ALWAYS_AUTH=true 「为true开启认证」
  • 方向2: 验证用户密码是有有错, 如下配置是否错误:
1
2
3
# 如果有配置用户密码, 验证 docker-compose.yml 配置的用户密码是否有错
DRONE_GIT_USERNAME=<username>
DRONE_GIT_PASSWORD=<password>

实现 场景一

  • 场景1:
    • 打包: 拉取代码 –> 更新依赖(npm i) –> 构建项目(build)
    • 部署: 删除旧的资源包 –> 替换新构建的资源包

知识点:

  • 将宿主机的卷轴映射(挂载)进Drone执行器里面 「公共卷轴」; 简要说明 Drone 提供的Volume
    • Host Volume:数据挂载到宿主机上与宿主机公用卷轴
    • Temporary Volume: 临时卷轴, 不同Step「步骤」共享, Pipeline「管道」 执行完毕后清除.
  • 使用Nginx简单部署打包产物
  • 拓展: 使用 appleboy/drone-scp 上传文件到另外的服务器
  • 拓展: 使用 Setting --> Secrets配置 储存敏感数据

前提条件:

  • 有可以正常打包访问的前端项目(本例子是由vite脚手架, 简单构建出来的ts-react项目)
  • 部署服务已安装nginx, 并可以正常使用

drone和部署的服务在同一台主机

PS: 在同一台部署服务器, 直接共享卷轴, 就可以完成打包并部署

重要说明:

  • 通过与宿主机共享Volume, 缓存node_modules 「每次构建都是全新的drone-runner-docker容器, 共享卷轴可以省去install时间」
  • drone服务和部署服务器同一台主机, 而主机上又有nginx. 通过共享目录, 达到直接部署的目的

项目的.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
29
30
31
# 项目的.drone.yml 文件
kind: pipeline # 定义一个管道
type: docker # 定义管道类型
name: build-test1 # 定义管道名称

# 声明宿主机 映射到 drone执行器的数据卷
volumes:
- name: node_modules # 数据卷名称
# Host Volume, 挂载到宿主机上的卷轴
host:
# 宿主机的绝对路径
path: /home/gite/drone/cache/node_modules
- name: web_build_dir
host:
path: /usr/share/nginx/test1

steps:
- name: build-project # 步骤名称
image: node:16.13.1 # 使用镜像和版本
depends_on: [clone] # 依赖 clone 步骤,
volumes: # 当前步骤使用(挂载)的卷轴
- name: node_modules # 数据卷名称
path: /drone/src/node_modules # 容器内的绝对路径
- name: web_build_dir
path: /drone/src/dist
# 执行的命令
commands:
- pwd # 查看当前目录 `/drone/src`
- npm config set registry https://registry.npm.taobao.org # 切换淘宝镜像
- npm install # 安装依赖
- npm run build # 执行构建指令
  • 检查构建物 ll /usr/share/nginx/test1
  • 浏览器访问查看效果

drone和部署的服务不在同一台主机

重要说明:

  • 配置secrets, drone配置界面 Setting --> Secrets配置 储存敏感数据
  • 同上, 共享node_modules
  • drone官网插件
  • 使用 appleboy/drone-scp 镜像进行上传文件 地址
  • 官网还有一个cschlosser/drone-ftps插件用ftp上传, 试了半天愣是没成功
    • 官网插件的文档和github 的文档不是一样的「估计是镜像和仓库应该就是不一样的」
    • 一直在运行~~
    • 感觉需要ftp还是自己写个sh吧

项目的.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 项目的.drone.yml 文件
kind: pipeline # 定义一个管道
type: docker # 定义管道类型
name: build-test1 # 定义管道名称

# 声明宿主机 映射到 drone执行器的数据卷
volumes:
- name: node_modules # 数据卷名称
# Host Volume, 挂载到宿主机上的卷轴
host:
# 宿主机的绝对路径
path: /home/gite/drone/cache/node_modules
# 已经不需要共享此卷轴了
# - name: web_build
# host:
# path: /home/git/drone/web_build/test1
# path: /usr/share/nginx/test1

steps:
- name: build-project # 构建项目步骤
image: node:16.13.1 # 使用镜像和版本
depends_on: [clone] # 依赖 clone 步骤,
volumes: # 当前步骤使用(挂载)的卷轴
- name: node_modules # 数据卷名称
path: /drone/src/node_modules # 容器内的绝对路径
# - name: web_build
# path: /drone/src/dist
# 执行的命令
commands:
- pwd # 查看当前目录
- npm config set registry https://registry.npm.taobao.org # 切换淘宝镜像
- npm install # 安装依赖
- npm run build # 执行构建指令
# - tar -zcvPf tmp.tar.gz /drone/src/dist/* # 有打包需要再打包

- name: deploy-project # 上传文件步骤
image: appleboy/drone-scp
depends_on: [build-project] # 依赖 build-project 步骤,
settings:
# 服务器地址, 账号, 密码
host: o2packs.com # 不使用secrets, 明文
username:
from_secret: deploy_username # 使用secrets
password:
from_secret: deploy_password
# 需要上传的文件 「需要相对路径, 如果用绝对路径会整条路径打包上传」
# source: ./dist # 单个
source: # 多个
# - !* # 全都忽略
- ./dist
# 上传的目录文件夹
target: /usr/share/nginx/test1
# ps: 移除的目录是test1, 将source所有中定义的所有内容放入test1目录中
rm: true
port: 22
command_timeout: 2m

实现 场景二(Docker)

  • 场景2(Docker):
    • 打包: 拉取代码 –> 更新依赖(npm i) –> 构建项目(build) –> 打包镜像(DockerFile) –> 推送到镜像仓库
    • 部署: SSH连接到服务器 –> 拉取新镜像 –> 停止和移除旧容器 —> 启动新容器

知识点:

  • drone多个pipeline使用
  • 利用Dockerfile打包docker镜像
  • 利用 appleboy/drone-ssh 插件远程到部署服务器部署项目

前提条件:

  • 有可以正常打包访问的前端项目(本例子是由vite脚手架, 简单构建出来的ts-react项目)
  • 部署服务器已安装docker和docker-compose
  • 部署服务器允许密码登陆 「PS: 若使用SSH, 请参考官网修改

项目的.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
kind: pipeline # 定义一个管道
type: docker # 定义管道类型
name: build-test1 # 定义管道名称

# 声明宿主机 映射到 drone执行器的数据卷
volumes:
- name: node_modules # 缓存
host:
path: /home/gite/drone/cache/node_modules

# 这里禁用是没有效果的, 因为第一步clone默认执行
# clone:
# disable: false # 禁用代码拉取

steps:
- name: build-project # 步骤名称
image: node:16.13.1 # 使用镜像和版本
depends_on: [clone] # 依赖 clone 步骤,
volumes: # 当前步骤使用(挂载)的卷轴
- name: node_modules # 数据卷名称
path: /drone/src/node_modules # 容器内的绝对路径
# 执行的命令
commands:
- pwd # 查看当前目录
- npm config set registry https://registry.npm.taobao.org # 切换淘宝镜像
- npm install # 安装依赖
- npm run build # 执行构建指令

- name: build-image # 构建镜像
image: plugins/docker
depends_on: [build-project] # 依赖build-project
settings: # 当前设置
username: # 账号名称
from_secret: docker_username
password: # 账号密码
from_secret: docker_password
dockerfile: deploy/Dockerfile # Dockerfile地址, 注意是相对地址
repo: soulweapon/test1 # docker仓库名称

---

# 新的pipeline
kind: pipeline
type: docker
name: deploy

depends_on: # 依赖build管道
- build-test1

clone:
disable: true # 禁用拉取、

steps:
- name: deploy-project
image: appleboy/drone-ssh
settings:
host: o2packs.com
username:
from_secret: deploy_username # 使用secrets
password:
from_secret: deploy_password
port: 22
command_timeout: 2m
script:
- echo ==-----==开始部署==-----==
- docker pull soulweapon/test1:latest
- docker-compose -p test1 down
# - docker volume rm xxx # 有挂载卷轴的记得卸载
- docker-compose -f /home/ubuntu/compose-file/test1.yml -p test1 up -d
# 过滤出dockerImages的id, 删除none镜像
- docker rmi $(docker images | grep test1 | grep none | awk '{print $3}')
- echo ==-----==部署成功==-----==

必备文件1「deploy/Dockerfile」:

1
2
3
4
5
6
7
8
9
10
11
# 基于nginx镜像
FROM nginx:latest

# 复制打包文件
COPY ./dist /usr/share/nginx/html

# 复制配置文件
COPY ./deploy/nginx.conf /etc/nginx

# 容器应用端口
EXPOSE 80

必备文件2「deploy/nginx.conf」:

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
events {
worker_connections 1024;
}

http {
include mime.types;
default_type text/html;
sendfile on;
keepalive_timeout 65;
charset utf-8;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;

server {
listen 80;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}

# 反向代理
# location ~* /api/(.*) {
# resolver 8.8.8.8;
# proxy_set_header Host $proxy_host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-NginX-Proxy true;
# proxy_pass $SERVER_URL/$1$is_args$args;
# }
}
}

必备文件3「部署服务器 - /home/ubuntu/compose-file/test1.yml」:

1
2
3
4
5
6
7
8
9
version: '3.0'

services:
nginx:
image: soulweapon/test1:latest
container_name: test1_web # 服务名称
restart: always # 重启方式
ports:
- "8088:80"

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @Kocher 创建,使用 Stellar 作为主题。