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 的映象即可