Uncategorized

Drone CI/CD 配合 Github 使用 Rsync 進行 Deploy

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

設定 url 兩個 url 時,如果有使用 port 記得也要補上
使用 ngrok 的話不需要帶上 port
authorization callback url 為 domain + /login
設定完後,就能取得 cline id 與 client secret

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
啟動後且啟動成功~ 可以看見目前 dorne 服務的 url
此時~
可以試著打開瀏覽器 (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 己經開始處理任務了~

activate 想要動作的 Git Repo
也可以查看目前的建置情況
接下來,只要有任一 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 是否正確

檢查 url、port 是否對應正確
同頁~ 下方也可以檢查 webhook 是否正確送達

Ref

參考內容:

  • 之前文章提到的 『什麼是 CI/CD’- 備註 & 障礙排除 – 什麼是 CI/CD
可樂

Recent Posts

plain PHP 搭配 Slack 進行錯誤追蹤、回報(Error Tracking、Error Handling)

錯誤追蹤、回報非常重要,看到的錯誤才知道怎麼修。現今 PHP 流行的 Laravel 有很好的 Error Tracking, Error Handling。但 plain PHP 怎麼辦呢? 在 production 為了安全考量會設定…

4 years ago

Nginx brotli 設定

網頁壓縮技術中 gzip 很好用,deflate 己經過時,但你聽過 brotli 嗎? 有著比 gzip 更好、更快的壓縮效率。看起來利大於弊有什麼不用他的理由嗎?簡單從優、缺點來看 brotli!到底 brotli 布羅特利是什麼、如何設定呢。 目前大多的 web server…

4 years ago

本機使用 Docker 容器內 PHP (wrapper/expose PHP)

為什麼要讓本機使用 Docker 內 PHP? 情境... docker 容器內用的是 PHP 7.4 但你的開發本機還在跑 PHP 5.6 或是更舊,因為 dockerize 的關係會將所有相關環境都轉移到…

4 years ago

為什麼你需要密碼管理工具

為什麼你需要密碼管理工具現代人一天下來需要輸入多少組密碼,工作與生活己經和密碼密不可分! 除了足夠全安的密碼,密碼記錄、儲存的方式又足夠安全嗎?密碼管理工具可以帶來什麼幫助呢? 為什麼你需要密碼管理工具 資安問題!!大多人說著沒做壞事不怕被偷資料、監聽。嚴重曝露出現代人的基本科技素養的低落和無知 🤯 密碼的使用無所不在!! 行動裝置的普及,APP 、手機遊戲、銀行帳戶所有和生活相關的東西都需要密碼!!facebook, line 只要打開 APP 也會輸入密碼只是他是自動輸入、一般情況不可視 (auth token) 一般人最常發生的密碼資安問題…

4 years ago

簡單使用 Mysql Partition 優化查詢

mysql 資料表分區 mysql table partition 從架構上調整 mysql 的查詢效率。mysql DB 的優化可以簡單也能複雜,除了調整設定值。也可以透過水平分割(Horizontal Partitioning)、垂直分割(Vertical Partitioning) 分庫或分表將資料分散儲存減少資料搜尋、group by 時的效能消耗。拆開批次處理,理論上效率都會變好,本文就水平分割的…

4 years ago

如何 Debug Node APP 配合 Docker 與 VsCode

透過 vscode Debug 利用中斷點 (breakpoints) 讓開發、偵錯更聰明。 加快除錯速度,而不是用傳統的 console log 方式查看變數、物件內容找問題。 本篇教你如何用 vscode + node +…

4 years ago