序論:CI/CD 和自動部署的重要性

為了提高開發工作流程的效率,自動部署,即 CI/CD(持續整合/持續交付)已經成為不可或缺的選擇。如果在將代碼推送(Push)到 GitHub 時,構建-測試-部署過程可以自動進行,那麼開發生產力將大大提高。

實現這種自動部署的方法有很多,但主要有兩種:一是利用 GitHub 自帶的 GitHub Actions,二是通過 GitHub 的 Webhook 功能來直接實現部署邏輯。

為什麼需要自己實現 Webhook 而不是使用 GitHub Actions?

GitHub 貓咪將 Webhook 飛機扔給 Tux 的場景

GitHub Actions 無疑是一個強大且方便的 CI/CD 工具。通過幾行 YAML 文件,可以定義複雜的工作流程,並通過多種行動市場自動化構建、測試、部署等許多過程。在大多數項目中,GitHub Actions 是一個極佳的選擇,這一點無可否認。

但在所有情況下,GitHub Actions 並不是最佳選擇。特別是對於以下情況的開發者來說,使用 GitHub Webhook 進行直接實現可能會更具吸引力。

  • 對成本敏感的個人開發者或小型團隊:GitHub Actions 在公共存儲庫中幾乎是無限制免費的,但在私有存儲庫中,超過一定的免費配額(分鐘和存儲)將會產生費用。若希望徹底消除預期外的費用產生風險,直接實現會是答案。

  • 正在運行 Raspberry Pi 5 等自造暫存伺服器的開發者:如果已經擁有物理伺服器(包括 VPS、雲實例),那麼不必出租 GitHub 的虛擬環境(Runner),而是最好充分利用自家伺服器的資源。在自己的伺服器上直接接收和部署代碼更加符合成本效益,從資源使用的角度也更具優勢。

  • 希望對部署邏輯進行完全控制和自由的開發者:GitHub Actions 使用標準的工作流程和行動,但直接實現 Webhook 可以讓你完全設計和控制部署腳本的每一部分。當需要特定於某環境的複雜自定義邏輯或與既有管道的完美整合時,這將顯得尤為強大。

在這個系列文章中,我們將詳細介紹如何利用 GitHub Webhook 在我的伺服器上直接實現部署邏輯。我們將以Python 開發者為目標,特別是使用簡單而強大的網頁框架FastAPI來構建 Webhook 端點。DRF(Django REST Framework)也是個極好的選擇,但由於僅僅是處理 Webhook 請求的輕量邏輯,我認為 FastAPI 是最佳選擇。正如去超市只需要簡單的車子,沒必要開著跑車去。

構建自動部署系統的基本準備材料

實際的實現將從下一篇開始。在這篇文章中,我將整理進行流暢所需提前準備的事項。

  1. GitHub 存儲庫:

    • 需要一個包含要應用自動部署的 Python 項目的 GitHub 存儲庫。(公開或私有均可)

    • 每當將代碼推送到該存儲庫時,部署就會開始。

  2. 暫存伺服器(自我託管伺服器):

    • 需要實際進行部署的伺服器。Raspberry Pi 5、個人 VPS(虛擬專用伺服器)、雲實例(如 AWS EC2、GCP Compute Engine 等)均可。

    • 必須能通過公用 IP 地址或域名從外部(GitHub)訪問。(需注意防火牆設置。)

    • 建議使用Ubuntu Server等 Linux 環境作為操作系統。

    • 安裝 Docker: 應確保服務器上已提前安裝 Docker,以便部署的應用能基於 Docker 容器進行構建或運行。

  3. Python 開發環境:

    • 暫存伺服器上必須安裝 Python 3.8 以上版本。(建議使用虛擬環境)
  4. Git:

    • 暫存伺服器必須安裝 Git。用於從 GitHub 存儲庫中使用 git pull 命令提取最新代碼。
  5. FastAPI 和 Uvicorn:

    • 用於實現 Python Webhook 端點的框架FastAPI和 ASGI 伺服器Uvicorn也是必要的。我們將在下一篇中介紹安裝和基本設置。
  6. SSH 金鑰:

    • 為了安全地訪問 GitHub 存儲庫並提取代碼,需要設定 SSH 金鑰。大多數人可能已經在自己的帳戶中註冊了 SSH 金鑰。(尚未註冊的朋友們請到 GitHub 註冊。使用部署金鑰 Deploy key 一般是常見的選擇。)
  7. 對網頁伺服器(Nginx 或 Apache2)及域名/HTTPS 設定的理解:

    • GitHub Webhook 通常建議使用 HTTPS 進行安全通信。因此,強烈建議提前準備像 deployer.example.com 這樣的子域名,並為該域名申請HTTPS 證書(例如通過 Let's Encrypt 獲取免費的證書)

    • 我相信不會有人直接將 FastAPI 應用通過端口轉發連接到互聯網 ISP 的路由器,但為安全起見,我還是要補充說明,應用程序應該使用Nginx 或 Apache2作為反向代理(Reverse Proxy)來將 Webhook 請求轉發到 FastAPI 應用,這樣的配置一般是安全的,並且能夠很好地保障安全性。務必使用服務器程序設置反向代理。對這一基本理解及設定經驗的掌握將對你大有裨益。

  8. 對 Systemd 服務的理解(雖然可選但建議):

    • 這個 FastAPI Webhook 伺服器需要在暫存伺服器上常駐並運行。建議將其註冊為 Systemd 服務,以便在伺服器重啟時自動啟動,並且便於管理服務(啟動/停止/重啟)。

    • 參考:在 Docker 容器內部直接執行 gitdocker 命令以構建複雜的部署邏輯是不符合容器設計目的的,還需要 docker-in-dockerdocker-out-of-docker 等複雜設置,並對安全性不好。如果服務器已經安裝了 gitdocker,應當輕鬆地將 FastAPI Webhook 伺服器作為 Systemd 服務運行,並在部署腳本中直接使用系統的 gitdocker 命令,這將更加高效和簡潔。在這個系列文章中,我們將以這種方式為主進行說明。


現在所有準備都已完成。下一篇文章中,我們將詳細介紹如何在準備好的暫存伺服器上構建 FastAPI Webhook 端點並設置 GitHub Webhook,以成功完成第一次自動部署。敬請期待!