1. 程式人生 > >乾貨:自動部署其實很簡單

乾貨:自動部署其實很簡單

應用場景

如果你希望本地執行git push到git伺服器後,在目標伺服器上直接拉取程式碼並進行部署的話,可以參考下本教程。

背景

ui同學平時把素材包都放在git.ui的git倉庫中,幾個版本迭代下來,整個倉庫的大小已經達到了1.7g,每次clone都很艱難...

直到有一天,有人在群裡建議可以直接掛在服務直接訪問...

對話

思路

拆分這個需求,有兩個點需要實現:

  1. 在目標機器上部署,可以訪問到靜態檔案。
  2. 在倉庫被push的時候,自動通知目標機器執行步驟1

進一步拆分,從這兩個角度出發,第一個點有很多實現方案,在這裡羅列幾種實現方案:

  1. 掛載到目標節點上,使用node設定靜態檔案路徑,採用框架生成相應的檔案目錄。
  2. 將專案的靜態內容上傳到cdn上,並將所有的靜態內容生成檔案索引入口。
  3. 當用戶訪問某個Url時,通過stash API去拉取相關的目錄資料,並生成目錄結構或靜態檔案吐給使用者,來實時更新目標檔案。

這裡以第一種方案為例,來具體實現一下。

因此整個流程需要分成三端,客戶端(新變更推送)、git伺服器(git掛載伺服器)、目標伺服器(進行自動部署的伺服器)。考慮到第二點,在倉庫被push的時候,要自動觸發訊息。自然想到使用githook來處理(githook的介紹可以看這篇)。但是githook中不管是客戶端鉤子還是服務端鉤子都只能在客戶端和服務端之間雙向連結,因此需要使用git伺服器的webhook功能(

webhook介紹)。整個流程如下圖:

流程圖

實現

由上面思路流程,node服務需要區分請求的型別:

  • GET請求:根據url進行靜態檔案重定向
  • POST請求:收到webhook請求,執行指令碼,拉取git倉庫

關於靜態檔案部署,調研了兩個npm包:stserve-handler。兩者都可以進行靜態資源部署,但是經測試,st對中文命名的目錄名支援不好,會出現亂碼,serve-handler對中文目錄支援比較好,故選擇serve-handler。

關於執行指令碼拉取倉庫,有兩種方案推薦,一種是node執行指令碼或執行命令列命令的方式child_process,利用子程序進行指令碼的執行,另外一種是第三方的

shelljs,是在child_process的基礎上的封裝,呼叫系統命令更簡單。故選擇第二種。

因此具體程式碼如下:

var http = require('http');
// 靜態檔案部署
var handler = require('serve-handler');
// 執行shell命令
var shell = require('shelljs');

http.createServer(function(request, response) {
  var urlMethod = request.method;
    if(urlMethod === 'POST') {
  		// 拿到POST請求,輸出內容並執行git pull操作
      console.log("POST request");

      var content = "";
      request.on('data', function (chunk) {
        content += chunk;
      });

      request.on('end', function () {
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.write("You've sent: " + content);
        response.end();
        console.log("POST data:",content);
      });
      try{
      	 // 拉取最新程式碼
        shell.exec("git pull");
        console.log("POST success");
      }catch(e) {
        console.log("POST fail");
      }
      return;
    }else {
    	// GET請求,直接呼叫serve-handler來靜態資源重定向
    	console.log("GET request");
    	console.log("GET url", request.url);
    	return handler(request, response, {
 		  "public": "git.ui"
   		});
    }
}).listen(8080);

console.log('Server started');
複製程式碼

在目標伺服器上用pm2部署服務,同時在git伺服器上設定webhook的觸發地址,完成目標伺服器的部署。

後續

後續可以註冊服務和域名,將機器繫結域名,或利用現有服務配置Nginx對映。

大家有興趣的可以試著實現以下第二種第三種訪問靜態檔案的部署方案。