Drone-比Jenkins更輕量化的持續整合部署工具
Drone 簡介
Drone 是一個基於Docker容器技術的可擴充套件的持續整合引擎,由GO語言編寫,可用於自動化測試與構建,甚至釋出。每個構建都在一個臨時的Docker容器中執行,使開發人員能夠完全控制其構建環境並保證隔。相對於常見的Jenkins,選中 Drone的原因在於它非常簡潔,不像Jenkins那樣複雜,同時它擁有可以滿足基本需求的能力,並且提供了許多實用的外掛,如GitHub
,Email
,微信
,釘釘
等。
Drone 官方地址:https://www.drone.io/
Drone 開源地址:https://github.com/harness/drone
由於本人是在公司內部伺服器部署的,所以都是使用的HTTP
Drone 版本 2.9.1
Gitea 版本 1.17.6
Docker 版本 20.10.12
Harbor 版本 1.10.10
倉庫專案 .NET5
Drone CI-Gitea
Drone官方文件 中支援的Git倉庫有很多種:
本文示例也選用相對Gitlab
更輕量化的Gitea
,演示Gitea版本為:1.17.6,Gitea
部署不是本文重點,請移步其他文章。
建立OAuth2金鑰
登入Gitea後,點選右上角頭像選擇設定(如果沒設定選項,需要管理員許可權
然後選擇 應用,在最下面建立OAuth2應用,填寫名稱和重定向URI:
點選建立後,會跳轉到這個頁面,記住 客戶端ID和 客戶端金鑰,後面部署Drone會用到,客戶端金鑰在退出本頁面時候就會顯示為*,所以尤其需要記住 客戶端金鑰,然後點選儲存。
Docker-Compose部署
Drone
資料儲存預設使用 sqlite
資料庫。並且提供支援 postgres
和 MySql
官方文件中強烈建議使用 postgres
而非 mysql
。 某些操作在 mysql
未得到優化。 https://docs.drone.io/server/storage/database/
PS: 支援 postgres9.6 及更高版本 、 mysql:5.6 及更高版本
DockerCompose.yml:
# 在執行DockerCompose前,需要建立網路 docker network create drone
version: '3.9'
# 建立自定義網路
networks:
drone:
name: drone
driver: bridge
services:
# Drone的資料庫服務
db:
# 拉取的映象名稱和版本號
image: postgres:latest
# 容器名稱
container_name: drone_db
# 該容器隨Docker啟動而啟動
restart: always
# 加入到drone網路
networks:
- drone
# 埠對映,左邊宿主機埠:右邊容器內部埠
ports:
- '7931:5432'
environment:
- POSTGRES_USER=drone # PGSQL預設使用者
- POSTGRES_PASSWORD=drone # PGSQL預設密碼
- POSTGRES_DB=drone # PGSQL預設資料庫
volumes:
# 資料永續性掛載宿主機 左邊宿主機路徑:右邊容器內路徑
- /volumes/drone/db:/var/lib/postgresql/data
# Drone Server 服務
server:
image: drone/drone:2.9.1 # 目前drone最新版本為 2.9.1
container_name: drone_server
# 該容器隨Docker啟動而啟動
restart: always
# 加入到drone網路
networks:
- drone
# 埠對映,左邊宿主機埠:右邊容器內部埠
ports:
- '7929:80'
environment:
- DRONE_SERVER_PROTO=http # 訪問協議,建立webHooks和重定向
- DRONE_SERVER_HOST=192.168.2.7:7929 # 主機名稱,建立webHooks和重定向
# 與 drone runner 通訊的金鑰 可以在 伺服器(Linux) 中使用 openssl 生成金鑰
- DRONE_RPC_SECRET=e1ad8a7f3dbc68ca9c21bcc949335009
# 設定管理員賬戶,username和Gitea賬戶名稱需要一致
- DRONE_USER_CREATE=username:young,admin:true
- DRONE_DATABASE_DRIVER=postgres # 資料庫型別
- DRONE_DATABASE_DATASOURCE=postgres://drone:drone@db/drone?sslmode=disable # 資料庫連線
- DRONE_GIT_ALWAYS_AUTH=true # 使用 oauth 身份驗證資訊拉取程式碼
- DRONE_GITEA_SERVER=http://192.168.2.7:3000 # gitea伺服器地址
- DRONE_GITEA_CLIENT_ID=2c921d85-e40e-41f8-90e0-c77c383786b5 # gitea 客戶端 id 剛才建立的OAuth2的客戶端Id
- DRONE_GITEA_CLIENT_SECRET=ZVZoRWK6jR5mqgAIm6sB5VX6C2LPK1sYKv4hQWyTdULu # gitea 客戶端 金鑰 剛才建立的OAuth2的客戶端金鑰
- DRONE_GITEA_SKIP_VERIFY=false # 禁用 gitea 連結時 tls 驗證
volumes:
# 資料永續性掛載宿主機 左邊宿主機路徑:右邊容器內路徑
- /volumes/drone/server:/data
- /var/run/docker.sock:/var/run/docker.sock
# 依賴的容器
depends_on:
- db
# Drone Docker Runner
runner:
image: drone/drone-runner-docker:1.8.0 # 目前drone-runner-docker最新版本為 1.8.0
container_name: drone_runner
restart: always
networks:
- drone # 加入到drone網路
ports:
- '7930:3000'
environment:
# 名稱
- DRONE_RUNNER_NAME=docker-runner
- DRONE_RUNNER_CAPACITY=10 # 限制runner可執行的併發管道數量 預設為2
- DRONE_RPC_PROTO=http # 訪問drone server 協議
- DRONE_RPC_HOST=server # 訪問drone server 伺服器地址
# 與 drone server 通訊的金鑰, 需與上面Server的 DRONE_RPC_SECRET 值相同
- DRONE_RPC_SECRET=e1ad8a7f3dbc68ca9c21bcc949335009
- DRONE_UI_USERNAME=admin # Drone Runner 的 UI 使用者賬號
- DRONE_UI_PASSWORD=qwe123 # Drone Runner 的 UI 使用者密碼
volumes:
- '/var/run/docker.sock:/var/run/docker.sock'
depends_on:
- server
將上述儲存,檔名為:drone-docker-compose.yml
docker-compose 執行命令:
docker-compose -f drone-docker-compose.yml up -d
# -f dockerfile檔名,不使用-f引數時,預設就為 docker-compose.yml
# -d 後臺啟動並執行容器
如果未報錯,那麼docker就啟動成功了,使用Portainer檢視容器狀態:
顯示都為running狀態。
部署成功後啟用儲存庫
部署成功後,訪問7929埠的頁面:
點選Continue會自動跳轉到Gitea的授權頁面:
如果你瀏覽器沒有登陸Gitea,會先讓你登陸:
登陸且授權後,就會跳轉到Drone的頁面了,只需要授權一次即可,往後我們登入了Gitea就直接進入Drone了。
進入Drone會看到未啟用的倉庫,選擇需要啟用的倉庫,然後我們點選啟用它:
啟用成功後,回到Gitea檢視被啟用的倉庫,就會看到倉庫已經自動的配置好了WebHook(Web鉤子):
點選鉤子,進去找到測試推送,點選測試推送,如果出現如下綠色,那鉤子就沒問題了:
踩坑小Tips:
如果是紅色,且HTTP相應內容包含
context deadline exceeded (Client.Timeout exceeded while awaiting headers)
,請檢查你的倉庫根目錄是否存在Drone的.drone.yml
配置檔案,我就是這個配置檔案放錯了地方卡了我大半天。。。
到這裡我們的Drone就安裝完畢了,啟用倉庫後,我們向倉庫推送一個commit,Gitea就會發送訊息通知Drone去自動構建了!
配置Drone的自動構建
Drone支援不同環境的不同管道配置,這裡我使用Docker Pipelines管道配置簡單來說就是Drone的每一步操作都在一個臨時的Drone的容器中進行,容器操作完會自動銷燬,容器之間會共享當前的工作目錄。
本人這裡使用了私有映象倉庫 Harbor
,Harbor
的搭建文章點選此處。
Drone 配置檔案 .drone.yml
如下:
kind: pipeline # 預設為 pipeline
type: docker
name: deployment # 構建檔名稱
steps: # 陣列結構,流水線化的構建步驟
# 步驟1 構建
- name: build # 因為drone支援同時書寫多個構建任務,所以需要為本任務起個名字
pull: if-not-exists # 如果映象不存在則拉取,免去每次都要重新下載
image: mcr.microsoft.com/dotnet/sdk:5.0 # 本步驟執行在哪個docker映象中,該映象必須存在於 docker hub 中,可在 https://hub.docker.com/_/microsoft-dotnet-sdk 檢視對應版本號
commands: # 構建過程中,將會依次執行的命令,如果命令退出碼非0,將會終止構建本次構建
- dotnet restore # 專案重建
- dotnet build -c Release # 專案生成構建
- echo ========專案生成成功======== # 輸出
# 步驟2 將映象推送到 Harbor
- name: publish 2 harbor
pull: if-not-exists # 如果映象不存在則拉取,免去每次都要重新下載
image: plugins/docker
settings:
dockerfile: Demo/Dockerfile # Dockerfile 在專案中的位置
tags: latest # 生成映象後的Tag標籤
insecure: true # 是否不安全
registry: 192.168.2.7:8088 # 私有映象倉庫地址
repo: 192.168.2.7:8088/zhjs/drone-ci-demo # 倉庫地址/Harbor專案名稱/自定義映象名稱
username:
# 從drone倉庫配置中祕密空間讀取使用者名稱
from_secret: docker_username
password:
# 從drone倉庫配置中祕密空間讀取密碼
from_secret: docker_password
# 步驟3 使用ssh訪問主機,拉去映象並執行部署
- name: deploy
pull: if-not-exists # 如果映象不存在則拉取,免去每次都要重新下載
image: appleboy/drone-ssh
settings:
# 需要部署的主機地址
host: 192.168.2.7
# 主機ssh埠
port: 22
# 主機登陸使用者名稱
username: root
password:
# 從drone倉庫配置中祕密空間讀取密碼
from_secret: ssh_pwd
script:
- echo =========暫停並刪除舊容器========
- docker stop drone-ci-demo-1 && docker rm drone-ci-demo-1
- docker stop drone-ci-demo-2 && docker rm drone-ci-demo-2
- echo =========刪除舊映象=============
- docker rmi 192.168.2.7:8088/zhjs/drone-ci-demo:latest
- echo ========從harbor拉取最新映象========
- docker pull 192.168.2.7:8088/zhjs/drone-ci-demo:latest
- echo ===============執行映象==========
- docker run --name drone-ci-demo-1 -p 5555:80 -d 192.168.2.7:8088/zhjs/drone-ci-demo:latest
- docker run --name drone-ci-demo-2 -p 5556:80 -d 192.168.2.7:8088/zhjs/drone-ci-demo:latest
- echo ========部署成功========
# 步驟4 部署完成,郵件通知
- name: notify
pull: if-not-exists # 如果映象不存在則拉取,免去每次都要重新下載
image: drillster/drone-email
settings:
recipients_only: true # 只發送給指定郵件收件人,不預設傳送給流水線建立人
host: smtp.qq.com #SMTP伺服器 例如 smtp.qq.com
port: 465 #SMTP服務埠 例如QQ郵箱埠465
subject: "Drone Build Complete!" # 郵件主題內容
username: #郵箱使用者名稱
from_secret: qqmail_username
password: #郵箱密碼
from_secret: qqmail_pwd
from:
from_secret: qqmail_username
recipients: #收件人
from_secret: email_recipients # 格式:xxxx,xxxx
when: #執行條件
status:
- success
- changed
- failure
檔案編寫完成後,把程式碼git push
到倉庫中,Gitea會通知Drone進行部署,Drone找到.drone.yml
配置檔案,就會按照配置檔案中的步驟進行構建了,部署期間可以在Drone中檢視到每一步的部署情況
首次部署的速度可能略慢,最終部署成功圖:
總結:對於小團隊來說,總體是完全可以接受的,自動部署一旦配置好了,所有的編譯/測試/打包/部署的工作就交給Drone去完成了,而我們只需要專注於我們的程式碼編寫就行了!