如何使用 GitHub 將程式碼部署到你的伺服器

當你把程式碼從 GitHub 自動部署到自己的伺服器時,可以節省時間並避免出錯。部署自動化能夠帶來更快的回饋,也有助於團隊更高效地協作。藉助 GitHub Actions、Webhook 和部署腳本等工具,你可以減少人為失誤,讓整個流程更加穩定可靠。即使你只掌握了 GitHub 和伺服器管理的基礎知識,也能建立這套工作流程,並很快看到改善效果。
重點整理
- 將程式碼部署自動化可以節省時間並減少錯誤。使用 GitHub Actions 和 Webhook 等工具,可以讓流程更加順暢。
- 準備好必要的工具和帳戶,包括 GitHub 儲存庫、雲端伺服器以及部署腳本。這些基礎設定是成功實現自動化的關鍵。
- 透過 SSH 金鑰實現免密碼存取,保障伺服器安全。這能確保只有受信任的系統可以連線到你的伺服器。
- 在正式上線前,先在預備伺服器上測試部署流程。這樣可以及早發現問題,保護正式環境。
- 使用 GitHub Secrets 安全儲存敏感資訊。這可以讓密碼和金鑰不會暴露在工作流程檔案中。
自動部署的前置條件
所需工具與帳戶
在開始設定自動部署之前,你需要準備一些必要的工具和帳戶。它們將幫助你把 GitHub 上的程式碼連接到伺服器,並讓整個流程更加順暢。
- 線上遠端儲存庫:你需要一個 GitHub 帳戶,並擁有一個存放專案程式碼的儲存庫。
- 本機 Git 儲存庫:在你的電腦上設定一個本機 Git 儲存庫,用於管理程式碼變更。
- 雲端伺服器:選擇一個雲端伺服器供應商,例如 Amazon EC2 或 Rackspace。你的網站或應用程式將執行於此。
- 部署腳本:撰寫一個部署腳本,例如
deploy.php,用來拉取 GitHub 上的最新程式碼。 - 在伺服器上安裝 Git:請確認你的伺服器已安裝 Git,且版本為最新。
- SSH 金鑰設定:在伺服器上產生 SSH 金鑰,以實現與 GitHub 的安全免密碼通訊。
- 將 SSH 公鑰加入 GitHub:把伺服器的 SSH 公鑰加入你的 GitHub 帳戶中,以便伺服器能夠存取儲存庫。
- 設定 Post-Receive Hook:在 GitHub 中設定 post-receive hook,用來觸發你的部署腳本。
提示:請妥善保管你的 SSH 金鑰。絕不要將私鑰分享給任何人。
準備你的伺服器
你必須先準備好伺服器,以便接收來自 GitHub 的程式碼更新。這樣的設定可以確保每次自動部署都能順利執行。
- 將你的 GitHub 儲存庫複製到伺服器上的某個目錄。你可以為正式環境和預備環境分別建立不同的目錄。
- 撰寫 Bash 部署腳本,並賦予這些腳本執行權限,以便它們能夠取得最新程式碼並執行。
- 訂閱 GitHub 的 Webhook API。這樣你的伺服器就能監聽事件,並在需要時自動開始部署流程。
下面是一個簡單的儲存庫複製命令:
git clone git@github.com:yourusername/your-repo.git
完成這些步驟後,你的伺服器就可以進行自動部署了。每次部署新程式碼時,你都能節省時間並減少錯誤。
使用 GitHub Actions 自動部署程式碼
你可以藉助 GitHub Actions 將程式碼自動部署到伺服器。這個工具可以幫助你在每次推送變更時自動執行腳本並發佈程式碼。你不再需要手動登入伺服器或手動執行命令,整個過程會更加流暢且可重複。
建立工作流程檔案
要實現程式碼自動部署,你需要在儲存庫中建立一個工作流程檔案。這個檔案會告訴 GitHub Actions:當你推送新程式碼時,需要執行哪些操作。請將該檔案放在 .github/workflows/ 目錄中,並命名為類似 main.yml 的名稱。
下面是一個工作流程檔案範例:它會在每次推送標籤時觸發,並執行部署工作:
name: Deploy on Tag on: push: tags: - '*' jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout Repository uses: actions/checkout@v3 - name: Deploy to Test Server env: REMOTE_PATH: [your remote path location] if: startsWith(github.ref, 'refs/tags/') && contains(github.ref, 'rc') run: | mkdir -p ~/.ssh echo "${{ secrets.TEST_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa cd ~/.ssh chmod 600 id_rsa ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa ${{ secrets.TEST_SSH_USERNAME }}@${{ secrets.TEST_SERVER }} 'echo "${{secrets.REPO_DEPLOY_KEY}}" > ~/.ssh/gh_key && chmod 600 ~/.ssh/gh_key && eval `ssh-agent -s` && ssh-add ~/.ssh/gh_key && cd ${{ env.REMOTE_PATH }} && git fetch --tags && git checkout ${{ github.ref }} && /usr/bin/docker compose run --rm backend php yii migrate --interactive=0 && /usr/bin/docker compose run --rm backend php yii cache/flush-all && rm -f ~/.ssh/gh_key'
這個工作流程會先簽出你的程式碼,然後連線到伺服器,並執行命令來更新專案。你可以根據自己的需求調整這些步驟。
在建立工作流程檔案時,你可能會遇到一些常見問題:
- 工作流程沒有觸發。請確認檔案位於
.github/workflows/main.yml。 - YAML 語法錯誤。請確保每一級縮排使用兩個空格。
- 找不到命令。請檢查 GitHub runner 上是否安裝了所有所需工具。
你可以透過反覆檢查檔案位置和語法來避免這些問題。
設定環境與 Secrets
在自動部署程式碼時,你必須確保伺服器安全。絕不要把密碼或私鑰直接寫進工作流程檔案。相反地,你應該使用 GitHub Secrets 來儲存敏感資訊。
進入你的儲存庫設定頁面,找到「Secrets」部分。新增 SSH 私鑰、伺服器使用者名稱以及其他敏感資訊。在工作流程檔案中,你可以使用 ${{ secrets.YOUR_SECRET_NAME }} 的形式來引用這些 Secrets。這樣可以確保你的資料安全且不會外洩。
你也可以為測試環境和正式環境分別設定不同的 Environment。這樣一來,你可以先把程式碼自動部署到測試伺服器;如果一切正常,再部署到正式伺服器。藉助 GitHub Actions,你可以精確控制程式碼在何時、部署到哪裡。
按照這些步驟操作後,每次你推送變更時,程式碼都會自動部署。你將節省時間、減少錯誤,並讓整個部署流程更加穩固、安全。
使用 Webhook 實現自動部署
Webhook 是實現部署自動化的一種非常有力的方式。設定完成後,你的伺服器可以監聽來自 GitHub 的事件,並在收到通知後自動更新程式碼。如果你希望在自己的伺服器上掌控整個部署流程,這種方法會非常適合。
撰寫 Webhook 監聽腳本
首先,你需要一個用於監聽 Webhook 請求的腳本。你可以使用 PHP、Node.js,或其他能夠處理 HTTP POST 請求的語言。這個腳本會在你向儲存庫推送變更時接收來自 GitHub 的通知。
下面是一套典型的 Webhook 監聽器設定流程:
- 將你的 Git 儲存庫分別複製到正式環境和預備環境對應的目錄中。
- 為每個環境建立 Bash 腳本,並賦予這些腳本執行權限,以便自動執行。
- 撰寫處理 Webhook 事件的程式碼。許多開發者會在 Node.js 中使用
github-webhook-handler套件,但你也可以使用 PHP 或 Python。 - 在 GitHub 儲存庫設定中配置 Webhook URL。選擇用來觸發 Webhook 的事件,例如 push 或 pull request。
- 測試並驗證你的設定。你可以使用 PM2 這類行程管理工具來監控腳本,並透過日誌排查錯誤。
下面是一個簡單的 PHP Webhook 監聽腳本範例:
<?php
$secret = 'your_webhook_secret';
$payload = file_get_contents('php://input');
$signature = 'sha1=' . hash_hmac('sha1', $payload, $secret);
if (hash_equals($signature, $_SERVER['HTTP_X_HUB_SIGNATURE'])) {
// Run your deployment script
shell_exec('/path/to/deploy.sh');
http_response_code(200);
echo "Deployment triggered.";
} else {
http_response_code(403);
echo "Invalid signature.";
}
?>
提示:一定要使用 GitHub 提供的範例 payload 測試你的 Webhook 監聽器。這樣可以幫助你在影響線上網站之前發現錯誤。
設定 GitHub Webhook
建立好監聽腳本之後,你還需要在 GitHub 儲存庫中設定 Webhook。這一步會把你的儲存庫和伺服器連接起來,並告訴 GitHub 應該把通知送到哪裡。
按照以下步驟設定你的 Webhook:
- 撰寫處理 Webhook 事件的程式碼,並確保你的伺服器擁有一個 GitHub 可以存取的公開 URL。
- 如果你想簡化事件處理流程,可以使用像
github-webhook-handler這樣的套件。 - 執行你的服務程式,讓它開始監聽傳入的 Webhook 請求。
- 進入 GitHub 儲存庫設定頁面,新增一個 Webhook,並填寫監聽腳本的 URL。
- 選擇應該觸發 Webhook 的事件,例如 push 事件或 pull request。
在使用 Webhook 時,安全性非常重要。你需要確保只有 GitHub 才能觸發伺服器上的部署。以下是一些關鍵的安全注意事項:
| 安全注意事項 | 說明 |
|---|---|
| 使用密鑰進行驗證 | 為你的 Webhook 新增一個密鑰,以幫助確認請求確實來自 GitHub。 |
| Webhook URL 的可存取性 | 請妥善保護你的 Webhook URL,不要隨意公開,以防止未經授權的存取。 |
| 使用 HTTPS | 設定 HTTPS,以加密 GitHub 與伺服器之間的通訊。 |
注意:如果你使用了密鑰,請同步更新監聽腳本,以驗證傳入請求的簽章。這會增加一層額外的安全保護。
完成這些步驟後,每次你向儲存庫推送程式碼,伺服器都會自動部署最新版本。這樣的設定可以節省時間,並減少手動操作帶來的風險。
安全的伺服器存取與 SSH 金鑰
設定安全存取機制,是任何自動化部署流程中都非常關鍵的一部分。你需要確保只有受信任的使用者和系統能夠連線到伺服器。使用 SSH 金鑰可以幫助你實現安全、免密碼的連線。
產生 SSH 金鑰
你可以透過產生 SSH 金鑰,讓部署流程安全地連線到伺服器。請依照以下步驟為部署使用者設定 SSH 金鑰:
- 在本機上產生一對新的 SSH 金鑰:
ssh-keygen -t ed25519 -f ~/.ssh/blog_deployer - 在伺服器上建立一個專門用於部署的使用者:
useradd blog-deployer - 鎖定該使用者的密碼,防止其透過密碼登入:
passwd -l blog-deployer - 為新使用者建立一個
.ssh目錄:mkdir -p /home/blog-deployer/.ssh - 將公鑰加入
authorized_keys檔案中:nano /home/blog-deployer/.ssh/authorized_keys - 變更主目錄的擁有權:
chown -R blog-deployer:blog-deployer /home/blog-deployer
這樣設定之後,就只有你的部署系統才能連線到伺服器並將專案部署到伺服器上。
設定權限
你必須設定正確的權限,才能確保部署過程的安全。如果權限設定不當,攻擊者可能會取得存取權限,甚至竊取資料。以下是一些最佳實務:
- 限制部署使用者的 SSH 登入能力。你可以使用如下命令:
restrict,pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding,command="/usr/local/bin/rrsync -wo /var/www/blog" - 限制部署使用者可執行的操作,只允許執行部署所需的最小權限操作。
- 將 Secrets 和金鑰保存在安全的保管庫中,並確保其在靜態儲存和傳輸過程中都經過加密。
- 定期稽核並監控伺服器存取情況。
- 定期輪替 SSH 金鑰和各類敏感憑證。
提示:務必檢查 SSH 金鑰和部署腳本的權限設定。權限設定錯誤可能會導致未經授權的存取、資料外洩或遭受攻擊。
遵循這些步驟後,你就能更好地保護部署流程,並確保伺服器安全。
測試並部署你的網站
執行一次測試部署
在將網站部署到正式環境之前,你應當始終先進行測試。測試部署可以幫助你及早發現問題,並確保整個流程符合預期。請依照以下步驟,從 GitHub 向你的私有伺服器執行一次測試部署:
- 準備你的伺服器。使用一個乾淨的 Linux 系統,例如 Ubuntu 22.04 或更新版本。確保伺服器至少具備 4GB 記憶體和 2 個 CPU 核心,並確認它可以連上網際網路。
- 從 GitHub 複製你的部署儲存庫。使用正確的 SSH 金鑰或 HTTPS 方式來確保存取安全。
- 選擇你的安裝方式。如果你想快速安裝,可執行:
./scripts/install-fast.sh如果你需要自訂安裝,請先準備好設定檔,然後使用 Helm 安裝命令。
- 觸發部署。向儲存庫推送一次變更,或手動觸發工作流程或 Webhook。
- 查看伺服器日誌,確認部署腳本已經執行並成功更新檔案。
提示:在將網站部署到正式環境之前,請務必先在預備伺服器上測試。這能夠保護你的線上網站安全。
排解常見問題
在部署過程中,你可能會遇到一些常見問題。下表列出了常見錯誤、成因以及預防措施:
| 問題 | 錯誤訊息 | 原因 | 預防措施 |
|---|---|---|---|
| 映射中發現重複鍵 | duplicate key found in mapping | YAML 解析器更新 | 在範本中使用唯一且描述清楚的命名 |
| 找不到 Secret | Secret not found or variable is empty | 語法錯誤 | 在範本中展示正確的上下文語法 |
| 矩陣策略錯誤 | Matrix not expanded, tests skipped | 無效的矩陣設定 | 在範本中提供一個可正常運作的矩陣範例 |
| 上下文語法錯誤 | Variable not interpolated, value is empty | 忘記使用 ${{ }} 包裹 | 在範本中展示所有上下文模式 |
| 範本過於複雜 | Contributor ignores template, issue incomplete | 包含 20 個以上欄位 | 保持技能類範本精簡(最多 5-8 個欄位) |
| 缺少必填欄位 | Issue incomplete, missing key information | Markdown 範本缺少驗證 | 使用帶有 required: true 的 YAML 範本 |
| 工作流程重複 | Wasted CI time, high maintenance overhead | 為 CI / CodeQL / dependency review 分別設定了獨立工作流程 | 在範本中提供整合方案 |
如果你遇到錯誤,請檢查 YAML 檔案中是否存在問題。確認所有 Secrets 和變數都已正確設定。查看部署日誌通常可以幫助你快速定位原因。及早修正這些小問題,會讓你的部署流程更加順暢可靠。
你應該經常測試部署流程,並保持部署腳本的安全性。你也可以嘗試一些更進階的工具,例如 AWS Code Deploy、Heroku、Zeit Now、Netlify、Travis CI、CircleCI、AWS ECS、Docker Swarm 和 Kubernetes。對於行動端專案,也可以使用 Bitrise 和 Firebase。為你的 GitHub 整合加入通知系統,可以幫助你更好地監控部署狀態。這些工具能夠幫助你管理 Git 工作流程,並讓你的雲端伺服器保持最新。自動化檢查、監控工具和視覺化儀表板,會為你帶來更強的掌控力與安全性。
