jenkins、circleci、travis 或 Gitlab CI 皆為目前暫知名的 CI/CD 服務,各自缺點也不言而喻…
過於肥大、收費略高(?)、速度不夠快執問題…
此時使用 go language 開發的 Drone 就出現啦,完全 docker 容器化的運行方式讓整個 CI / CD 流程、速度提升到一個新的境界(誇張 🤪)
Drone 執行流程
在開始前~先簡單瞭解 Drone 的執行流程~
從下面的流程圖可以看出整體動作的起源在於 Git
可以是 github, gitlab, bitbucket 或是任一自架的 Git 服務都可以~
其重點是: Git 服務會發送 webhook 至你自己架設的 Drone 服務
設定與安裝 Drone
安裝 Drone 最重要的一步!
您必須有一個開放、外部可連線的 domain 或 IP
從上文的 Drone 執行流程得知 git push 之後的觸發動作 (webhook) 是需要一個開放網址讓 git 服務進行通知。
沒有 domain 或 IP 的人可以參考使用 ngrok 服務
ngrok 可以很快速的將本機 port 開放至 internet (將提供一個亂數網址)
可以參考 Bo-Yi 大神的 Drone 教學影片 & 文章
『用五分鐘安裝好 Drone 搭配 GitHub 自動化環境』
https://www.youtube.com/watch?v=-U2EXs0tmN0
https://blog.wu-boy.com/2020/02/install-drone-with-github-in-five-minutes/
上面兩篇文章,你就可以離開 Cola 教室了 XD
官網文件也有簡單的 docker + drone + github 的設定教學
https://docs.drone.io/server/provider/github/
Github OAuth Apps 申請
開始前~ 先申請 github oauth app
Github >Settings >Developer settings > OAuth Apps
取得
Client ID 與 Client Secret
注意: 設定 url, 和 callback url
docker compose 上建立 Drone
Drone 是一個以 docker 容器為主的服務,安裝上當然也是首選 docker 囉~
因為我還有其它 web 服務,希望所有 web 服務的露出都透過 nginx 處理,
所以我還另開了 nginx,不讓 drone web UI直接曝露。
如果使用 ngork 可以將 nginx servcie 的部分刪掉、不使用~
(對 docker 沒概念的人可以參考 https://github.com/cscolabear/docker-dev)
docker-compose.yml example
version: '3.7'
services:
nginx:
hostname: docker-nginx
image: fholzer/nginx-brotli:v1.18.0
ports:
- 80:80
- 443:443
volumes:
- ${VOLUMES_DRIVER}:/var/www:delegated
- ./Logs:/var/log/nginx:delegated
- ./Dockerfiles/nginx/sites-enabled:/etc/nginx/sites-enabled:ro
depends_on:
- drone-server
networks:
- app_net
drone-server:
image: drone/drone:1
ports:
- 8080:80
volumes:
# 設定本機的 Database 目錄存放 drone 服務相關資料
- ./Database/drone:/data
environment:
- DRONE_SERVER_HOST=${DRONE_SERVER_HOST}
- DRONE_SERVER_PROTO=${DRONE_SERVER_PROTO}
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
- DRONE_USER_CREATE=${DRONE_USER_CREATE}
- DRONE_USER_FILTER=${DRONE_USER_FILTER}
# GitHub Config
- DRONE_GITHUB_SERVER=https://github.com
# 至 github OAuth Application 申請、取得 id 與 secret
- DRONE_GITHUB_CLIENT_ID=${DRONE_GITHUB_CLIENT_ID}
- DRONE_GITHUB_CLIENT_SECRET=${DRONE_GITHUB_CLIENT_SECRET}
# deubgu 時可以拿掉下面三個註解
# - DRONE_LOGS_DEBUG=true
# - DRONE_LOGS_PRETTY=true
# - DRONE_LOGS_COLOR=true
networks:
- app_net
drone-runner:
image: drone/drone-runner-docker:1
restart: always
depends_on:
- drone-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 128M
restart_policy:
condition: on-failure
environment:
- DRONE_RPC_HOST=${DRONE_RPC_HOST}
- DRONE_RPC_PROTO=${DRONE_RPC_PROTO}
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
- DRONE_RUNNER_CAPACITY=1
networks:
- app_net
networks:
app_net:
driver: "bridge"
上面 yml 內看見類似… ${VOLUMES_DRIVER}
這是讓 docker-compose 由 .env 讀入的環境變數
下面為 .env 的內容 (example)
# 本機電腦裡的 Web 專案目錄位置
VOLUMES_DRIVER="~/my_web_projects/"
# 使用 ngrok 提供的亂數 domain
DRONE_SERVER_HOST= apo2r385963.ngrok.io
# ngrok 預設提供 https
DRONE_SERVER_PROTO=https
# 自行至 command line 輸入 openssl rand -hex 16,將生成的內容復制貼上
DRONE_RPC_SECRET=ax1234e8948s4cbcirbb4b4ifn29932nd
# drone runner: 直接使用 drone server 的 docker container name
DRONE_RPC_HOST=drone-server
DRONE_RPC_PROTO=http
# 使用前面動作在 github 申請來的 oauth app id 與 secret
DRONE_GITHUB_CLIENT_ID=dxxxxxxxxxxx8
DRONE_GITHUB_CLIENT_SECRET=2xxxxxxxxxxxxxxxxxxx5
# 設定 drone 使用者權限(也可以直接參考下一個章節~)
DRONE_USER_CREATE=username:cscolabear,admin:true
DRONE_USER_FILTER=cscolabear,cola_team,colapig
關於 Drone Authorization
上面 .env 裡設定的…
DRONE_USER_CREATE: 設定 id 是 cscolabear 的使用者為 admin
DRONE_USER_FILTER: 設定只有哪些 user id 或 organization 可以使用
多組情況下的設定為
e.g. DRONE_USER_FILTER=cscolabear,cola_team,colapig
未授權的使用者將收到這樣的訊息~Login Failed. User must be a member of an approved organization
啟動 Drone
上述的設定檔、參數都處理後之後,有幾種方式啟動 Drone 服務…
# 直接啟動,初期 debug 可以用這個方式查看 docker log
$ docker-compose up
# 啟動並將 docker 移到背景
$ docker-compose up -d
# 使用 ~/my-docker-compose.yml 這個設定檔啟動
$ docker-compose -f ~/my-docker-compose.yml up
# 啟動後,也可以用下面指令查看 drone server 的執行 log
$ docker-compose logs drone-server
Drone 搭配 Nginx (反向代理) – drone nginx reverse proxy
如果想使用 Nginx 反向代理 Drone 可以參考下面設定
ngork 的使用者可以直接略過這個部份
在前面步驟~
docker-compose.yml 設定了 nginx (volumes) sites-enabled 目錄
其目錄下新建一個 nginx conf
drone.conf example
server {
# listen 80;
# listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name local.drone;
access_log /var/log/nginx/drone.workxplay.net.access.log main;
error_log /var/log/nginx/drone.workxplay.net.error.log;
ssl_certificate /etc/nginx/ssl/default.crt;
ssl_certificate_key /etc/nginx/ssl/default.key;
location / {
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 http://drone-server;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
- 替換 server_name 的值為準備使用的 drone server domain
- 注意 access_log 與 error_log 的存放位置正確且可以正常寫入
- 不使用 ssl / https 就把 ssl_certificate 和 ssl_certificate_key 刪掉或註解
- location 內的設定可以直接使用,不需修改~
設定好 nginx conf 後重新啟動 nginx Service
$ docker-compose restart nginx
# or
$ docker-compose -f ~/my-docker-compose.yml restart nginx
Drone Secret
在編寫 .drone.yml 前,先設定 secret 值
drone secret 用於 .drone.yml 內,一些不想曝光或是隨時抽換的變數。
多數的 .drone.yml 都是開放的,如果把主機 IP 或是 ssh key 金鑰等存放在開放的 .drone.yml 其實不太恰當。
將這些不想曝光的值設定為 secret 後,可以在 .drone.yml 裡像直接引用~
針對各別Repository 做設定時可以使用 web ui (Per Repository)
https://docs.drone.io/secret/repository/
Repositories >[your repository] >SETTINGS >Secrets
.drone.yml 設定
接著移到 git repo,在專案裡加入 .drone.yml
設定 drone 的執行動作
在編寫 .drone.yml 時要注意、新舊版差異喔(本文為 drone 1.x)
step 為 drone 執行流程
.drone.yml example
kind: pipeline
type: docker
name: default
clone:
depth: 1
steps:
- name: node
image: node:12.17-slim
commands:
- npm install
- npm run dev
when:
branch:
- master
- name: rsync
image: drillster/drone-rsync
settings:
hosts:
from_secret: HOST
user:
from_secret: SSH_USER_NAME
key:
from_secret: USER_KEY
source: ./dist/
target:
from_secret: TARGET_PATH
recursive: true
delete: true
args: "--no-o --no-g -v"
# script:
# - ls -al
when:
branch:
- master
- name: slack
image: plugins/slack
settings:
webhook:
from_secret: SLACK_WEBHOOK
channel: drone-workxplay
link_names: true
username: "Drone Bot"
icon_emoji: ":robot_face:"
when:
status: [ success, failure ]
template: >
{{#success build.status}}
✅ build #{{build.number}} succeeded. Good job.
`{{repo.name}}/{{build.branch}}`
{{build.link}}
{{else}}
❌ build #{{build.number}} failed. Fix me please.
`{{repo.name}}/{{build.branch}}`
{{build.link}}
{{/success}}
secret 的呼叫方法
user:
from_secret: SSH_USER_NAME
如果不使用 secret
user: cola
或
user: "cola bear"
都設定完成後將 .drone.yml 加入想處理的 Git repo 並 git push~
接著進入 drone web ui,可以看到 drone 己經開始處理任務了~
Drone 的優、缺點
最後~ 來看一下 Drone CI/CD 的優點和缺點
優點 / pros:
- 服務本身安裝快速
- 任務啟動、執行速度快
- 支援的 Git 服務完整(github, gitlab, bitbucket….)
- docker plugin,所有流程、動作都是運行在 docker 容器內
php composer、npm run、test, ssh & git push, slack notify 每個動都由一個 docker 處理 - 可以自身客製 docker plugin
缺點 / cons:
- 剛開始發展,短期內改版頻繁
- Drone 和無人機同名 😬
google 查資料有點麻煩 XD - 官方文件更新不完整、不夠快…
- 0.x 版與 1.x 版的 yml 設定有大變動,在做設定的時候要注意…
障礙排除
Q. Git push 但是 Drone 沒有反應
A. 檢查 oauth client id, secret 都正確
再檢查 webhook 是否有接通
github 目標 repo >settings >Webhooks
檢查 url 是否正確
Ref
參考內容:
- 裡面的圖可以很清楚暸解 Drone 整個執行流程
『用 Drone 打造 CI/CD flow』
https://medium.com/asiayo-engineering/%E7%94%A8-drone-%E6%89%93%E9%80%A0-ci-cd-flow-36b9d14c7620
- 之前文章提到的 『什麼是 CI/CD’- 備註 & 障礙排除 – 什麼是 CI/CD