群友說的我站點訪問太慢。
因為部署在 Vercel 上,API 接口又在國內,通過 Zero 又套了一層,兩層下來在國內的訪問確實不是很好。
打算做一個在國內的鏡像站。
原本 Kami 是通過 GitHub Actions 做的,通過發版然後把產物發布到 Release,SSH 連接到伺服器之後再去拉取 GitHub Release,但是因為國內伺服器現在訪問 GitHub 真的太慢了,各大國內加速站也陸續掛壁了。
所以打算利用家用小主機完成本地部署,最後產物推送到雲伺服器。
問了群友之後,Drone CI 應該是個不錯的選擇,Go 寫的比較快也很輕量,可以非常簡單和 GitHub 綁定。
總體的流程大概如下:
流程比較簡單,接下來看看如何從零開始自建 Drone 和編寫這個流程。
Drone 部署#
Docker Compose 一把梭#
全程使用:Arch Linux + Docker 環境,其他環境僅供參考。
官方文檔寫的比較散,這裡我踩了很多坑。但是最後的配置的也沒有什麼特別的,我就直接貼這裡了。
name: drone
services:
drone-runner:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_RPC_PROTO=https
- DRONE_RPC_HOST=drone.innei.in
- DRONE_RUNNER_CAPACITY=2
- DRONE_RUNNER_NAME=runner
- DRONE_GITHUB_CLIENT_ID=
- DRONE_GITHUB_CLIENT_SECRET=
- DRONE_RPC_SECRET=
- DRONE_SERVER_HOST=
- DRONE_SERVER_PROTO=https
ports:
- 3000:3000
restart: always
container_name: runner
image: drone/drone-runner-docker:1
drone:
volumes:
- ./data:/data
environment:
- DRONE_GITHUB_CLIENT_ID=
- DRONE_GITHUB_CLIENT_SECRET=
- DRONE_RPC_SECRET=
- DRONE_SERVER_HOST=drone.innei.in
- DRONE_SERVER_PROTO=https
- DRONE_TLS_AUTOCERT=true
- DRONE_USER_CREATE=username:innei,machine:false,admin:true
ports:
- 80:80
- 443:443
restart: always
container_name: drone
image: drone/drone:2
networks:
mvlan:
ipv4_address: 10.0.0.47
networks:
mvlan:
external: true
上面配置缺失的環境變量需要去閱讀文檔,期間還需要創建一個自己的 GitHub App。
參考:
- https://docs.drone.io/server/provider/github/
- https://docs.drone.io/runner/docker/installation/linux/
Runner 別忘了,我就是因為忘了配置 Runner,倒是 CI 一直都在 Loading 狀態。
Drone 和 GitHub 連接是需要一個域名的(如果你沒有域名可以試試用內網 IP 的方式),因為 oauth 的方式,驗證成功之後會跳轉回你設定的地址。我這裡是 drone.innei.in。後續都按這個進行。
公網打洞#
上面配置之後,在內網 10.0.0.47 去登錄是無法登錄的,通過 GitHub oauth 之後會跳回配置的 drone.innei.in,但是這個地址我沒還配。
我使用 Cloudflare Zero Trust 進行打洞。非常方便。
這樣就好了。
進去之後,面板是空空的。這個沒有關係。到此 Drone 就搞定了。
Pipeline 編寫#
來到需要跑 CI 的 GitHub 倉庫,建立一個 .drone.yml
文件在根目錄,然後 push 到 GitHub,此時 drone 應該會出現這個 Repo,進入之後激活他。
kind: pipeline
name: build-and-package
platform:
os: linux
arch: amd64
steps:
- name: build
image: node:20-alpine
commands:
- 'npm i -g pnpm'
- 'pnpm install --no-frozen-lockfile'
- 'npm run build'
這步成功之後接下來就就是瘋狂調 pipeline 了。
由於 NextJS build 時候需要 .env
但是我又不想一個一個傳到 secrets,他不支持批量導入(能不能學學隔壁 Vercel),所以我想如何另一種方式傳入 env。這裡也花了很多時間。
首先想過用 http-server 托管 .env
,在 build 去下載它,因為在內網監聽,相對還是安全。後來發現 Drone 的 volume 映射可行,如果現在就用這個方案了。
Note
要使用 Volume 映射,你需要開啟 Trusted 選項。
在做這一步你需要先開啟管理員權限。如果是 docker 部署的,需要添加 ENV 到 Drone Server 中。 DRONE_USER_CREATE=username:innei,machine:false,admin:true
username
替換為 GitHub 用戶名。
重啟容器後,再次進入 Drone 的 Repo Settings,會看到 Project Settings - Trusted 然後打開它。
我這裡選擇的是,Drone 在每個步驟都是 Docker 運行時。
在每個 step 都可以映射一個 volume 到宿主機文件路徑。
我把項目需要的 .env
存放在 /home/innei/docker-compose/drone/public/shiro/.env
,在 build 的 step 添加 volume 映射。
volumes:
- name: shiro-env
host:
path: /home/innei/docker-compose/drone/public/shiro/.env
steps:
- name: build
image: node:20-alpine
commands:
- 'npm i -g pnpm'
- 'pnpm install --no-frozen-lockfile'
- 'npm run build'
volumes:
- name: shiro-env
path: /drone/src/.env
volumes 需要寫兩次,頂層的 volume 定義宿主機的絕對路徑和 volume 名稱,在 step 處則是 docker 重啟的絕對路徑。
我們可以把 build 和 deploy 拆分成兩個 pipeline。但是前後依賴。
然後 build 完成之後,需要產物臨時存儲。我選擇用 volume 方式,臨時放在 /tmp 下,供 deploy 獲取產物以推送到雲伺服器。
volumes:
- name: shiro-dist
host:
path: /tmp/shiro-dist
steps:
- name: build
image: node:20-alpine
commands:
- 'npm i -g pnpm'
- 'pnpm install --no-frozen-lockfile'
- 'npm run build'
volumes:
- name: shiro-env
path: /drone/src/.env
- name: dns
path: /etc/resolv.conf
- name: package
image: node:20-alpine
commands:
- 'pwd'
- 'ls -a'
- 'ls .next'
- 'apk add zip'
- 'sh ./standalone-bundle.sh'
volumes:
- name: shiro-dist # 這裡映射
path: /drone/src/assets
depends_on:
- build
然後在 deploy 使用 scp 和 ssh 。
ind: pipeline
name: deploy
platform:
os: linux
arch: amd64
volumes:
- name: shiro-dist
host:
path: /tmp/shiro-dist
steps:
- name: transfer file
image: appleboy/drone-scp
settings:
host:
from_secret: ssh_host
username:
from_secret: ssh_username
key:
from_secret: ssh_key
port: 22
target: /home/deploy/shiro
source:
- assets/release.zip
rm_target: true
strip_components: 1
debug: true
volumes:
- name: shiro-dist # 這裡 volume 可以獲取到 build pipeline 的產物
path: /drone/src/assets
- name: deploy
image: appleboy/drone-ssh
settings:
host:
from_secret: ssh_host
username:
from_secret: ssh_username
key:
from_secret: ssh_key
port: 22
script:
- '\npm install --os=linux --cpu=x64 sharp --registry=https://registry.npmmirror.com'
- cd ~/shiro
- unzip -o release.zip
- rm release.zip
- ls
- cd standalone
- cp -r ~/node_modules/sharp ./node_modules
- ~/.n/bin/pm2 restart ecosystem.config.js
debug: true
depends_on:
- transfer file
depends_on:
- build-and-package # 這裡依賴
ssh_
相關的則從 secrets 中獲取。
至此結束,我也就嘗試了四十幾周目😂。
成品配置#
https://github.com/Innei/Shiro/blob/main/.drone.yml
參考:https://www.timochan.cn/posts/jc/drone_workflows#Preface
此文由 Mix Space 同步更新至 xLog 原始鏈接為 https://innei.in/posts/Z-Turn/drone-self-host-ci-cd-with-github