一秀又、前言
作為一名前端菜雞单寂,服務(wù)器小白,剛開始在Linux
服務(wù)器上部署網(wǎng)站時(shí)吐辙,前端代碼我一般都是打包后手動(dòng)FTP
傳上去宣决,后端代碼直接在vscode
中使用SSH
連接服務(wù)器,直接同步代碼更改昏苏。
但小黑作為一個(gè)生命不息折騰不止的程序猿尊沸,肯定要探索更好玩更高效的方法,所以這次贤惯,咱就上手折騰了下自動(dòng)化部署方案
二洼专、準(zhǔn)備工作
1、持續(xù)集成服務(wù)(CI)方案選擇
實(shí)現(xiàn)代碼提交的自動(dòng)化工作流孵构,要依靠持續(xù)集成(CI)(或者加上持續(xù)交付(CD))服務(wù)∑ㄉ蹋現(xiàn)在主流的公用免費(fèi)的持續(xù)集成服務(wù)有:
Travis CI
Jenkins
Circle CI
Azure Pipeline
GitHub Actions
其中GitHub Actions是GitHub自家的持續(xù)集成及自動(dòng)化工作流服務(wù),簡(jiǎn)單易用颈墅,也是小黑本次使用的服務(wù)棒假。它使用起來(lái)非常簡(jiǎn)單,只要在你的倉(cāng)庫(kù)根目錄建立.github/workflows
文件夾精盅,將你的工作流配置(YAML文件)放到這個(gè)目錄下帽哑,就能啟用GitHub Actions服務(wù)。
小黑的網(wǎng)站是部署到騰訊云服務(wù)器上的叹俏,所以配置過(guò)程中用到了服務(wù)器相關(guān)配置妻枕,如果是想把網(wǎng)站放到GitHub Pages上,那只需要有個(gè)Github倉(cāng)庫(kù)就可以開始折騰起來(lái)了,下文關(guān)于遠(yuǎn)程服務(wù)器的配置可以忽略掉屡谐。
2述么、添加部署秘鑰
要把文件部署到遠(yuǎn)程服務(wù)器,首先要解決登錄校驗(yàn)的問(wèn)題愕掏。
比較常見的就是密碼登錄度秘、SSH密鑰登錄或者VNC登錄。小黑推薦使用SSH密鑰登錄饵撑,既方便有安全剑梳。
2.1、生成SSH密鑰對(duì)
相信需要遠(yuǎn)程部署到服務(wù)器的小伙伴肯定早就把SSH密鑰對(duì)配置好了滑潘,所以我們可以直接對(duì)應(yīng)的私鑰文件內(nèi)容復(fù)制一下垢乙,等下在GitHub中進(jìn)行配置就可以啦!這里小黑就不再贅述啦
2.2语卤、GitHub填寫自動(dòng)化配置項(xiàng)
SSH密鑰對(duì)生成后追逮,其實(shí)準(zhǔn)備工作就已經(jīng)完成的差不多了,最后一步就是將YAML文件中所需要的配置項(xiàng)粹舵,配置到Github上
首先打開對(duì)應(yīng)的倉(cāng)庫(kù)钮孵,點(diǎn)擊Setting > Secrets > New sceret
,然后將我們復(fù)制的密鑰文件內(nèi)容、服務(wù)器host和登錄用戶名都添加到配置如下圖對(duì)應(yīng)的配置中眼滤,這樣的話即使像小黑一樣把項(xiàng)目開源巴席,隱私信息也不會(huì)泄露啦。
配置完上面這些柠偶,我們的準(zhǔn)備工作就大功告成了,接下來(lái)就可以編寫工作流文件啦
三睬关、配置過(guò)程
1诱担、編寫工作流文件
在倉(cāng)庫(kù)根目錄中創(chuàng)建.github/workflows
文件夾,再創(chuàng)建一個(gè)YAML文件电爹,文件名自定蔫仙,我這里起名叫deploy.yml
,所以文件的完整路徑應(yīng)該為.github/workflows/deploy.yml
丐箩,配置的意義寫在注釋中啦摇邦,當(dāng)然小黑也會(huì)簡(jiǎn)略的介紹下重點(diǎn)配置項(xiàng)
1.1、文件基礎(chǔ)配置
首先就是YAML文件比較基礎(chǔ)的配置
on
里的內(nèi)容比較重要屎勘,指定自動(dòng)觸發(fā)工作流文件的事件施籍,也可以將工作流設(shè)置為只在某些分支、路徑或標(biāo)記上運(yùn)行概漱。比如小黑就是在當(dāng)master分支上進(jìn)行push時(shí)才會(huì)觸發(fā),然后忽略掉README.md
和LICENSE
文件的變更
jobs
里就是接下來(lái)所要運(yùn)行的所有工作流程丑慎,小黑就設(shè)置了build-production
這一個(gè)job,根據(jù)需要也可以設(shè)置多個(gè)
還有就是runs-on
,小黑第一次還以為是要填寫自己云服務(wù)器的操作系統(tǒng),就填了個(gè)centos
,一跑就報(bào)錯(cuò)竿裂,后來(lái)看了文檔才明白玉吁,這是配置用來(lái)運(yùn)行job的GitHub托管的新虛擬機(jī),和你所使用的操作系統(tǒng)及服務(wù)器系統(tǒng)無(wú)關(guān)腻异,和小黑一樣配置為ubuntu-latest
就行
strategy
中的node-version
可以不配置,為了和本地node版本統(tǒng)一进副,小黑配置了一下
steps
里就是所需要運(yùn)行的每一個(gè)具體的步驟啦,下面就讓小黑一一道來(lái)
name: Blog CI/CD
on:
push:
branches:
- master # 只在master上push觸發(fā)部署
paths-ignore: # 下列文件的變更不觸發(fā)部署,可以自行添加
- README.md
- LICENSE
jobs:
build-production:
runs-on: ubuntu-latest # 使用ubuntu系統(tǒng)鏡像運(yùn)行自動(dòng)化腳本(溫馨提示:和你所使用的操作系統(tǒng)及服務(wù)器系統(tǒng)無(wú)關(guān)悔常,我本地用的windows10,云服務(wù)器用的centos)
strategy: (可選)
matrix:
node-version: [12.x] # 配置所需node版本
steps: # 自動(dòng)化步驟
……
1.2影斑、下載代碼
這一步就是檢出你的倉(cāng)庫(kù)并下載里面的代碼到runner
中,actions/checkout@v2
是官方自己造的輪子,直接拿來(lái)用就行
- uses: actions/checkout@v2 # 第一步这嚣,檢出倉(cāng)庫(kù)副本
1.3鸥昏、配置node版本(可選)
這一步就是安裝node,輪子也是官方的,版本可以選填姐帚,使用npm進(jìn)行打包(不需要打包的項(xiàng)目可以省略1.3——1.5了)
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }} #規(guī)定node.js版本(可不配置)
1.4吏垮、安裝依賴
這一步就不用解釋了吧
- name: Install dependencies # 第二步,安裝依賴
run: npm install
1.5罐旗、打包代碼
這里小黑用了--if-present
標(biāo)志來(lái)避免腳本未定義時(shí)出現(xiàn)非零退出的情況膳汪,親測(cè)在目前項(xiàng)目中寫不寫都行九秀,不必糾結(jié)
- name: Build # 第三步遗嗽,打包代碼
run: npm run build --if-present
在部署服務(wù)器時(shí)小黑踩到了很大的坑,就是明明打包完成了鼓蜒,但就是不結(jié)束任務(wù)痹换,進(jìn)入下一步
都帶薪如廁回來(lái)了竟然還沒(méi)有完成Build任務(wù),這樣小黑都沒(méi)有煩躁也是多虧了和產(chǎn)品相愛相殺的磨練
換成yarn打包?失敗+1
修改node版本都弹?失敗+2
……娇豫??畅厢?冯痢??框杜?浦楣?失敗+N
是可忍叔不可忍,叔可忍他嬸子也不可忍了!
這是要逼小黑使出大殺招了!
面對(duì)疾風(fēng)吧咪辱!
…%…(¥@*(¥@)
看我一頓操作猛如虎~
最后振劳,在祭出三根寶貴的頭發(fā)之后,終于讓小黑找到了問(wèn)題所在
我變禿了油狂,也變強(qiáng)了澎迎! ——— 小黑
特么的竟然是打包后Node.js
進(jìn)程沒(méi)有終止庐杨,平時(shí)直接手動(dòng)Ctrl + C
就順便關(guān)了,根本沒(méi)注意到這個(gè)問(wèn)題夹供!
暴風(fēng)哭泣~
這時(shí)問(wèn)題又來(lái)了灵份,作為國(guó)服最菜前端,這webpack咱也只會(huì)個(gè)皮毛哮洽,觀察模式也并沒(méi)有開啟呀填渠,百度谷歌一頓搜,文檔咱也看了又看鸟辅,分析來(lái)分析去氛什,也不曉得是哪個(gè)在占用Node.js
進(jìn)程,索性快刀斬亂麻匪凉,一行process.exit(0);
直接亂殺枪眉!
push
一下試試,果然Build任務(wù)成功完成再层,我特么真是個(gè)天才贸铜,獎(jiǎng)勵(lì)自己美味飼料一斤!
1.6聂受、推送部署到服務(wù)器
打包成功蒿秦,接下來(lái)就是激動(dòng)人心的部署到服務(wù)器環(huán)節(jié)了,我們這里依然使用別人造好的輪子
DEPLOY_KEY
蛋济、SERVER_IP
棍鳖、USERNAME
就是我們剛開始在Github里配置好SSH私鑰、主機(jī)名碗旅、登錄名渡处,這里就不再贅述
主要需要留意的就是FOLDER
、和SERVER_DESTINATION
祟辟,也就是我們的推送文件夾及目標(biāo)文件夾医瘫,這里一定要將路徑寫正確。
源碼地址:rsync-deploy
- name: Deploy to Server # 第四步川尖,rsync推送文件
uses: AEnterprise/rsync-deploy@v1.0 # 使用別人包裝好的步驟鏡像
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} # 引用配置登下,SSH私鑰
ARGS: -avz --delete --exclude='*.pyc' # rsync參數(shù)茫孔,排除.pyc文件
SERVER_PORT: '22' # SSH端口
FOLDER: ./build/* # 要推送的文件夾叮喳,路徑相對(duì)于代碼倉(cāng)庫(kù)的根目錄
SERVER_IP: ${{ secrets.SSH_HOST }} # 引用配置,服務(wù)器的host名(IP或者域名domain.com)
USERNAME: ${{ secrets.SSH_USERNAME }} # 引用配置缰贝,服務(wù)器登錄名
SERVER_DESTINATION: /www/wwwroot/lmsworld.cn/ # 部署到目標(biāo)文件夾
我這里是直接將build文件夾內(nèi)文件替換到網(wǎng)站根目錄的馍悟,會(huì)存在非同名文件無(wú)法替換的情況,本來(lái)打算先刪除網(wǎng)站根目錄文件夾再替換的剩晴,但考慮到會(huì)有打包失敗或者部署失敗的可能性锣咒,刪除后網(wǎng)站會(huì)無(wú)法訪問(wèn)侵状,遂暫時(shí)不用此方法,后續(xù)有時(shí)間再繼續(xù)改進(jìn)毅整,寫在此處還是希望大佬們多多指點(diǎn)迷津~
1.7趣兄、重啟服務(wù)(視情況而定)
如果是僅僅是部署了前端代碼的話,那有可能就不用重啟服務(wù)了悼嫉,如果要后端代碼的話艇潭,就要重新啟動(dòng)服務(wù)了
可以在YAML配置文件里另加一個(gè)后端部署的job
,使用need
控制下工作流戏蔑,然后就在script
里依次寫下服務(wù)器上運(yùn)行的命令行即可蹋凝,小黑是用node寫的后臺(tái),僅供參考
- name: Restart server # 第五步总棵,重啟服務(wù)
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }} # 下面三個(gè)配置與上一步類似
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.DEPLOY_KEY }}
# 重啟的腳本鳍寂,根據(jù)自身情況做相應(yīng)改動(dòng),一般要做的是migrate數(shù)據(jù)庫(kù)以及重啟服務(wù)器
script: |
cd /www/server/web-server/
pm2 reload app.js
1.8情龄、完整配置文件
貼一下完整的配置文件迄汛,根據(jù)自己的項(xiàng)目情況修改下配置就行,不能用的話可以給小黑留言
name: Blog CI/CD
on:
push:
branches:
- master # 只在master上push觸發(fā)部署
paths-ignore: # 下列文件的變更不觸發(fā)部署刃唤,可以自行添加
- README.md
- LICENSE
jobs:
build-production:
runs-on: ubuntu-latest # 使用ubuntu系統(tǒng)鏡像運(yùn)行自動(dòng)化腳本(溫馨提示:和你所使用的操作系統(tǒng)及服務(wù)器系統(tǒng)無(wú)關(guān)隔心,我本地用的windows10,云服務(wù)器用的centos)
strategy:
matrix:
node-version: [12.x] # 配置所需node版本
steps: # 自動(dòng)化步驟
- uses: actions/checkout@v2 # 第一步,檢出倉(cāng)庫(kù)副本
- name: Use Node.js ${{ matrix.node-version }} #規(guī)定node.js版本(可不配置)
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies # 第二步尚胞,安裝依賴
run: npm install
- name: Build # 第三步硬霍,打包代碼
run: npm run build --if-present
- name: Deploy to Server # 第四步,rsync推送文件
uses: AEnterprise/rsync-deploy@v1.0 # 使用別人包裝好的步驟鏡像
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} # 引用配置笼裳,SSH私鑰
ARGS: -avz --delete --exclude='*.pyc' # rsync參數(shù)唯卖,排除.pyc文件
SERVER_PORT: '22' # SSH端口
FOLDER: ./build/* # 要推送的文件夾,路徑相對(duì)于代碼倉(cāng)庫(kù)的根目錄
SERVER_IP: ${{ secrets.SSH_HOST }} # 引用配置躬柬,服務(wù)器的host名(IP或者域名domain.com)
USERNAME: ${{ secrets.SSH_USERNAME }} # 引用配置拜轨,服務(wù)器登錄名
SERVER_DESTINATION: /www/wwwroot/lmsworld.cn/ # 部署到目標(biāo)文件夾
# - name: Restart server # 第五步,重啟服務(wù)
# uses: appleboy/ssh-action@master
# with:
# host: ${{ secrets.SSH_HOST }} # 下面三個(gè)配置與上一步類似
# username: ${{ secrets.SSH_USERNAME }}
# key: ${{ secrets.DEPLOY_KEY }}
# # 重啟的腳本允青,根據(jù)自身情況做相應(yīng)改動(dòng)橄碾,一般要做的是migrate數(shù)據(jù)庫(kù)以及重啟服務(wù)器
# script: |
# cd /www/server/web-server/
# pm2 reload app.js
2、最終效果
小黑迫不及待的將配置文件修改后push
到倉(cāng)庫(kù)颠锉,這次工作流跑的行云流水法牲,啥錯(cuò)都沒(méi)報(bào),簡(jiǎn)直完美琼掠!
在這個(gè)面板里你可以看到具體每一步任務(wù)的耗時(shí)與輸出信息拒垃,報(bào)錯(cuò)信息也可在這里查詢哦
最后如果你是部署到騰訊云、阿里云等云服務(wù)平臺(tái)的話瓷蛙,一般會(huì)收到一條安全警告通知悼瓮,比如小黑用的就是騰訊云
存在來(lái)自
ip:40.122.43.158
的異常登錄戈毒,這ip是誰(shuí)的,讓小黑查一下Microsoft數(shù)據(jù)中心横堡?應(yīng)該就是github服務(wù)器的ip了埋市,問(wèn)題不大,這里就先不管他了命贴,后續(xù)咱們?cè)僬曳椒ń鉀Q它
四恐疲、待優(yōu)化部分
小黑最近工作太忙,只是先簡(jiǎn)單實(shí)現(xiàn)了自動(dòng)化部署功能套么,但是還沒(méi)來(lái)得及進(jìn)行優(yōu)化培己,先留個(gè)坑,后續(xù)再更
1胚泌、緩存依賴加快工作流
2省咨、COS 優(yōu)化部署
五、參考
由于小黑見識(shí)淺薄玷室、水平有限零蓉,所寫內(nèi)容肯定有很多不足之處,還請(qǐng)各位大佬不吝賜教穷缤,十分感激敌蜂!
以下文檔、博客給了小黑極大的幫助津肛,在此表示炒雞感謝章喉!
1、GitHub Actions文檔
2身坐、How to deploy a create-react-app with github-actions
3秸脱、使用 GitHub Actions 實(shí)現(xiàn)博客自動(dòng)化部署
本篇文章由一文多發(fā)平臺(tái)ArtiPub自動(dòng)發(fā)布