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

使用 ngrok 的話不需要帶上 port
authorization callback url 為 domain +
/login

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

此時~
可以試著打開瀏覽器 (chrome) 進入 Drone web ui 試試
初次打開會被導向 github 授權畫面
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 己經開始處理任務了~

也可以查看目前的建置情況
接下來,只要有任一 git push 動作,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