Drone 管道機制
Drone
中引入了 管道(Pipeline)
機制。管道(Pipeline)
相當於一個流程,管道(Pipeline)
中可以執行多個 步驟(step)
。
步驟(step)
就是使用 插件(Plugin)
配置的操作。
與 Runner(執行器)
相同的是,管道(Pipeline)
也支持多種類型,用於適配不同運行環境。當然某些類型可以使用容器化代替統一管理。

Drone
也是使用 YAML
語法作配置文件,在配置文件可以同時配置多個 管道(Pipeline)
。
默認情況下多個 管道(Pipeline)
是並行執行,這也是 Drone
的強大功能之一:分布式管道系統
kind: pipeline # 定義一個管道
type: docker # 定義管道的類型
name: test # 定義管道的名稱
steps: # 定義管道的執行步驟
- name: test # 步驟名稱
image: node:latest # 當前Docker步驟使用的鏡像
commands: # 當前步驟執行的命令
- echo 測試drone執行2
在上一篇中配置的測試管道(Pipeline)
。此管道(Pipeline)
使用了 docker 類型。
管道(Pipeline)
中定義了一個步驟(step)
, 使用了 Node
鏡像。容器內執行了打印命令
整個自動化部署就是配置 步驟(step)
進行執行。
可以簡單的理解為, .drone.yml 配置文件相當於一個 .sh 文件,部署操作配置在這個文件中,交給 Drone
引擎執行。
下面就一步步編寫部署 Web
項目。
部署 Web 項目
Build 階段
上一篇中簡單的介紹,可以將整個部署流程划分為兩個階段:
- 拉取代碼 ---> 編譯項目 ---> 打包鏡像 ---> 推送鏡像倉庫
- 使用 SSH 連接服務器 ---> 拉取最新鏡像 ---> 停止和移除舊容器 ---> 啟動新容器。
可以以這樣流程划分構建管道(Pipeline)
。一個階段為一個 管道(Pipeline)
第一階段叫做 build
kind: pipeline # 定義一個管道
type: docker # 定義管道的類型
name: build # 定義管道的名稱
clone 代碼
默認情況下,管道(Pipeline)
執行的第一個步驟(step)
是 拉取代碼(clone)。
這是 Drone
提供的一個默認 步驟(step)
。
.drone.yml
文件可以使用 clone 屬性對此步驟(step)
設置。
默認的 clone 步驟(step)
只支持設置 disable、和 depth。
如果需要使用到其它參數,可以將默認的 clone 步驟(step)
禁用,自定義拉取代碼 步驟(step)
kind: pipeline # 定義一個管道
type: docker # 定義管道類型
name: build # 定義管道名稱
clone:
disable: false # 啟用代碼拉取
默認情況下, 拉取代碼使用的是 drone/git
鏡像。
部署 Drone
時可以使用 environment 屬性替換默認鏡像,可以參考官方文檔


編譯代碼
執行完畢 clone 步驟(step)
后就可以進行代碼編譯了。
代碼編譯可以直接使用 Node
鏡像執行 package.json
命令。
定義 build-project 步驟(step)
,執行代碼編譯。
在此 步驟(step)
中使用了 depends_on 屬性,這個屬性表示當前步驟(step)
需要依賴指定步驟執行,也就是需要在指定步驟執行完畢后才開始執行此步驟(step)
。
PS:
步驟(step)
之間是可以並發執行的。
kind: pipeline # 定義一個管道
type: docker # 定義管道類型
name: build # 定義管道名稱
clone:
disable: false # 啟用代碼拉取
steps:
- name: build-project # 步驟名稱
image: node:16.13.2 # 使用鏡像
depends_on: [clone] # 依賴的步驟,
commands: #執行命令
- npm config set registry https://registry.npm.taobao.org # 切換淘寶鏡像
- npm install # 安裝node_modules包
- npm run build # 執行編譯


PS: 如果是服務器中沒有
node:16.13.2
鏡像,首先會拉取鏡像,時間會更慢一些。
緩存 node_modules
如果多測試幾次代碼編譯步驟,會發現一個問題:每次代碼編譯執行時間都比較長,在我服務器執行時間大約 1 分鍾左右。
可以使用 Gitea
測試推送 Webhook
,進行重復測試。


查詢具體執行信息,會發現其中大部分時間都浪費在了 npm install
命令。

這是因為每一個步驟都是在一個進程內執行的,每一次執行都是一個新進程,
但是往往會有掛載數據這種情況,針對這種需求,Drone
也提供了 Volume
機制。允許將容器內文件掛載到宿主機中。
PS:
Drone
中代碼目錄在所有步驟(step)
中共享,
Drone
中提供了兩種 Volume
- Host Volume:數據掛載到主機上,數據永久存在
- Temporary Volume:數據掛載臨時卷中用於
步驟(step)
間共享。管道(Pipeline)
執行完畢會清除數據卷
具體兩者,可以參考官方文檔。
掛載數據卷分為兩步
- 聲明數據卷
- 使用數據卷
kind: pipeline # 定義一個管道
type: docker # 定義管道類型
name: test # 定義管道名稱
volumes: # 聲明數據卷
- name: node_modules # 數據卷名稱
host: # Host Volume
path: /volumes/drone/volumes/web/node_modules # 宿主機目錄 #絕對路徑
clone:
disable: false # 啟用代碼拉取
steps:
- name: build-project # 步驟名稱
image: node:16.13.2 # 使用鏡像
depends_on: [clone] # 依賴的步驟,
volumes: # 掛載數據卷
- name: node_modules # 數據卷名稱
path: /drone/src/node_modules # 容器內目錄 絕對路徑
commands: # 執行命令
- pwd # 查看當前目錄
- npm config set registry https://registry.npm.taobao.org # 切換淘寶鏡像
- npm install # 安裝node_modules包
- npm run build # 執行編譯
注意:
-
數據卷中路徑(path),必須為 絕對路徑,不可以使用 相對路徑。
我使用
pwd
命令查詢了當前目錄為 /drone/src,也就是
node_modules
的目錄為 /drone/src/node_modules -
使用數據卷必須開啟 Trusted 權限。 Trusted 權限需要管理員用戶設置
第一次構建會在宿主機中掛載 node_modules
數據,之后再構建就可以省去了 npm install
執行時間,大大提高了構建速度


構建鏡像
代碼編譯完畢后,下一個操作就是制作鏡像並推送倉庫了。
Drone
社區中提供了 plugins/docker
鏡像插件用於構建鏡像並將鏡像直接推送到鏡像倉庫。
kind: pipeline # 定義一個管道
type: docker # 定義管道類型
name: build # 定義管道名稱
- name: build-image # 步驟名稱
image: plugins/docker # 使用鏡像
depends_on: [build-project] # 依賴步驟
settings: # 當前設置
username: XXXXXX # 賬號名稱
password: XXXXXX # 賬號密碼
dockerfile: deploy/Dockerfile # Dockerfile地址, 注意是相對地址
repo: yxs970707/deploy-web-demo # 鏡像名稱
tags: # 鏡像標簽
- latest
- 1.0.2
settings 屬性是配置賬號、密碼、鏡像名稱等操作的屬性,這是 Drone
提供的屬性。 settings 屬性會傳給容器 environment 屬性。
plugins/docker
其它 settings 可以查詢官方文檔
在上述配置中使用了兩個 Tag
,加上了 latest
這個默認 Tag
。
PS: 注意,
Dockerfile
地址使用了相對路徑
PS:
Docker Hub
訪問會很慢。


Secret 配置賬號密碼
剛才構建鏡像時在 .drone.yml
文件使用了明文賬號密碼,這樣肯定是不允許的,可以使用 Secret
配置這樣的敏感數據。

kind: pipeline # 定義一個管道
type: docker # 定義管道類型
name: build # 定義管道名稱
- name: build-image # 步驟名稱
image: plugins/docker # 使用鏡像
depends_on: [build-project] # 依賴步驟
settings: # 當前設置
username: # 賬號名稱
from_secret: docker_username
password: # 賬號密碼
from_secret: docker_password
dockerfile: deploy/Dockerfile # Dockerfile地址, 注意是相對地址
repo: yxs970707/deploy-web-demo # 鏡像名稱
tags: # 鏡像標簽
- latest
- 1.0.2
使用Secret
時,需要使用 from_secret 屬性設置。
根據 package.json 生成 Tags
打包鏡像時設置的鏡像版本號,是直接設置的固定數值,這樣每次更新都要重新設置新版本號,也是一個繁瑣的操作。
Drone
中可以使用變量設置, 並且內置了許多變量,例如: DRONE_TAG
。但是個人感覺這些變量並不太好用。
我想要的效果是根據 package.json
文件 version 屬性 設置鏡像版本。這樣管理起來比較方便。
后查詢文檔發現 plugins/docker
鏡像支持讀取項目根目錄下 .tags 文件進行設置版本號

有一種解決方案,將package.json
文件 version 屬性寫入到 .tags 文件。
https://discourse.drone.io/t/using-custom-generated-tags-for-docker-images/1918/2
雖然感覺社區內會有這樣功能的鏡像插件,
但是查找起來浪費時間,於是自己寫了一個簡單的插件:https://github.com/yanzhangshuai/drone-web-tags
使用起來也很簡單,並且同時支持設置其它 Tags
。
steps:
- name: build-project # 步驟名稱
image: node:16.13.2 # 使用鏡像
depends_on: [clone] # 依賴的步驟,
volumes: # 掛載數據卷
- name: node_modules # 數據卷名稱
path: /drone/src/node_modules # 容器內目錄
commands: # 執行命令
- npm config set registry https://registry.npm.taobao.org # 切換淘寶鏡像
- npm install # 安裝node_modules包
- npm run build # 執行編譯
- name: build-tags
image: yxs970707/drone-web-tags # 使用鏡像
depends_on: [clone] # 依賴的步驟,
settings:
tags:
- latest # 設置其它tags, latest
- name: build-image # 步驟名稱
image: plugins/docker # 使用鏡像
depends_on: [build-tags, build-project] # 依賴步驟
settings: # 當前設置
username: # 賬號名稱
from_secret: docker_username
password: # 賬號密碼
from_secret: docker_password
dockerfile: deploy/Dockerfile # Dockerfile地址, 注意是相對地址
repo: yxs970707/deploy-web-demo # 鏡像名稱



deploy 階段
將鏡像推送到鏡像倉庫后,持續部署的第二階段就是在服務器更新部署。
第二階段雖然細分了許多操作,但關鍵是遠程連接服務器。所以為了簡單直接將這些操作都配置到一個 步驟(step)
第二階段 管道(Pipeline)
名字為 deploy
注意:管道(Pipeline)
之間需要使用 ---
相隔開

deploy 管道(Pipeline)
需要在 build 管道(Pipeline)
執行完畢后才執行。
並且 deploy 管道(Pipeline)
可以禁用代碼拉取
kind: pipeline
type: docker
name: deploy
depends_on: # 依賴build管道
- build
clone:
disable: true # 禁用拉取
SSH 連接並部署
之前說過,Drone
提供了多種 Runner(執行器)
和 管道(Pipeline)
類型, 但某些類型可以使用容器化統一化管理。
Drone
社區中提供了 SSH
連接鏡像插件, appleboy/drone-ssh
。
配置此步驟前,需要先改動 之前 web 項目的 Docker Compose
文件
- 配置中使用了具體
Tag
鏡像。不過服務器部署時並不需要清楚當前是什么版本服務,直接部署 最新版本(latest) 就行。 - 取消對 html 目錄的掛載。 html 數據並不推薦掛載到宿主機中,這樣版本管理會非常混亂

kind: pipeline
type: docker
name: deploy
depends_on: # 依賴build管道
- build
clone:
disable: true # 禁用拉取、
steps:
- name: deploy-project
image: appleboy/drone-ssh
settings:
host:
from_secret: server_host
user:
from_secret: server_username
password:
from_secret: server_password
port: 22
command_timeout: 2m
script:
- echo ====開始部署=======
- docker pull yxs970707/deploy-web-demo:latest
- docker-compose -p web down
- docker volume rm web-nginx
- docker-compose -f /yml/docker-compose/web.yml -p web up -d
- docker rmi $(docker images | grep deploy-web-demo | grep none | awk '{print $3}')
- echo ====部署成功=======
服務器部署步驟一共 5 個命令
- 拉取新鏡像
- 卸載舊容器
- 刪除 Volume
- 啟動新容器
- 刪除舊鏡像
第三個命令可以在 Docker Compose
使用外部 Volume
,這樣就不需要刪除 Volume
了。
最后一個命令是刪除舊的鏡像,當成功拉取新的 latest 鏡像,舊鏡像 Tag
會變成 none,所以刪除標簽為 none 的鏡像即可


