基於 Node.js 的服務器自動化部署搭建實錄
摘要:本文主要記錄我在服務器上使用 GitHub 的 Webhooks 進行網站自動化部署的過程。最終效果:開發終端向 Github 倉庫推送代碼后,服務器端自動拉取倉庫並重啟服務器。搭建過程主要參考了 lovelucy.info 的博客。
搭建環境:我正在使用的是 Vultr 的服務器,系統版本是 CentOS 7 x64。
在服務器上安裝 Node.js
最簡單的方法:從 EPEL 庫安裝 Node.js
$ sudo yum install epel-release
$ sudo yum install nodejs
// 檢查是否成功安裝
$ node --version
$ npm --version
(注:未經本人測試,版本可能相對較老。)
我個人搭建過程中使用了 Node.js 官網 的 Linux 二進制文件來安裝 Node.js。下載安裝包時要留意 Linux 的版本。(X86/X64)
// Node.js 安裝目錄
$ cd /usr/local/bin
// Node.js 官網提供的 Linux 二進制文件
$ wget https://nodejs.org/dist/v8.12.0/node-v8.12.0-linux-x64.tar.xz
// 解壓縮
$ tar xvJf node-v8.12.0-linux-x64.tar.xz
// 配置環境變量
$ vi /etc/profile
// 添加以下內容到文件末尾 ====================
export NODE_HOME=/usr/local/bin/nodejs
export PATH=$PATH:$NODE_HOME/bin
export NODE_PATH=$NODE_HOME/lib/node_modules
// 添加以上內容到文件末尾 ====================
// 保存退出后source一下,使其立即生效
$ source /etc/profile
// 檢查是否安裝成功
$ node -v
$ npm -v
至此,成功在服務器上安裝最新版本的 Node.js。
編寫拉取倉庫、重啟服務器腳本
一個可供參考的例子:deploy.sh
#!/bin/bash
WEB_PATH='/home/nodejs-be-demo'
echo "Start deployment"
cd $WEB_PATH
echo "pulling source code..."
git reset --hard origin/master
git clean -f
git pull
git checkout master
npm install
npm run start
echo "Finished."
配置 Github 倉庫的 Webhook 設置
- 在要配置的 Github 的設置頁面找到 Webhooks 選項,點擊「Add webhook」。
- 配置 Payload URL(接受 POST 請求的服務器 URL)。
- Secret(可以理解為配對暗號)。
- Content-type 選擇
application/json
。 - 其余默認設置即可。
配置 Node.js 腳本
在配置 Node.js 腳本之前,需要先安裝依賴,這里用到了一個中間件 github-webhook-handler ,以及進程管理服務 forever 。
$ npm install -g github-webhook-handler
$ npm install -g forever
腳本內容如下:deploy.js
var http = require('http')
var createHandler = require('github-webhook-handler')
var handler = createHandler({ path: '/autodeploy', secret: 'mySecret' })
// 上面的 secret 保持和 GitHub 后台設置的一致
function run_cmd(cmd, args, callback) {
var spawn = require('child_process').spawn;
var child = spawn(cmd, args);
var resp = "";
child.stdout.on('data', function(buffer) { resp += buffer.toString(); });
child.stdout.on('end', function() { callback (resp) });
}
http.createServer(function (req, res) {
handler(req, res, function (err) {
res.statusCode = 404
res.end('no such location')
})
}).listen(7777)
// 這里是監聽的端口號
handler.on('error', function (err) {
console.error('Error:', err.message)
})
handler.on('push', function (event) {
console.log('Received a push event for %s to %s',
event.payload.repository.name,
event.payload.ref);
run_cmd('sh', ['./deploy.sh'], function(text){ console.log(text) });
})
/*
handler.on('issues', function (event) {
console.log('Received an issue event for % action=%s: #%d %s',
event.payload.repository.name,
event.payload.action,
event.payload.issue.number,
event.payload.issue.title)
})
*/
這里 Node.js 監聽的是 7777 端口,你也可以使用 Nginx 反向代理到 80 端口。
用下面的命令測試一下,接收到 push 之后控制台會有輸出:
$ node deploy.js
如果沒什么問題,forever 就可以開起來了。
$ forever start deploy.js
其他問題
部署過程中可能遇到無法訪問對應端口的問題,需要檢查一下服務器的防火牆設置。大部分服務器都是白名單機制,只開放特定的端口。
CentOS 7 下默認使用的防火牆是 FirewallD,之前版本請搜索 iptables 。
另:FirewallD 和 iptables 的區別?
FirewallD 相關命令:
-
啟動服務,並在系統引導式啟動該服務
sudo systemctl start firewalld sudo systemctl enable firewalld
-
停止並禁用
sudo systemctl stop firewalld sudo systemctl disable firewalld
-
檢查防火牆狀態。輸出應該是 running 或者 not running。
sudo firewall-cmd --state
-
允許或拒絕任意端口/協議(如:12345端口,該規則在 public 區域)
sudo firewall-cmd --zone=public --add-port=12345/tcp --permanent sudo firewall-cmd --zone=public --remove-port=12345/tcp --permanent
-
重新加載 FirewallD 使規則立即生效
sudo firewall-cmd --reload
-
查看特定區域的所有配置
sudo firewall-cmd --zone=public --list-all
示例輸出:
public (default, active) interfaces: ens160 sources: services: dhcpv6-client http ssh ports: 12345/tcp masquerade: no forward-ports: icmp-blocks: rich rules:
更多詳細的 FirewallD 配置,請看 CentOS 上的 FirewallD 簡明指南。