Linux云服務(wù)器(本文使用的是阿里云Ubantu 22.04 64位)
SSH客戶端(使用的XShell, (https://www./en/free-for-home-school/) 可以下載免費(fèi)的家庭/學(xué)校版)
Github賬號(hào)以及能流程訪問
項(xiàng)目準(zhǔn)備
使用VS 2022新建一個(gè)空的ASP.NET Core Web API項(xiàng)目,框架選擇.NET 6.0。
因?yàn)樾枰褂肗ginx,這里就簡(jiǎn)單配置中間件轉(zhuǎn)發(fā)下 X-Forwarded-For
和 X-Forwarded-Proto
兩個(gè)header。
using Microsoft.AspNetCore.HttpOverrides; ... app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); app.UseAuthentication();
本地啟動(dòng)一下,看到swagger頁面,沒什么問題。代碼提交Github,接下來開始配置服務(wù)器.
服務(wù)器配置
所有包均使用 apt
命令進(jìn)行安裝,如果安裝過程提示 Unable to locate package 錯(cuò)誤,請(qǐng)先執(zhí)行如下命令后,再重新安裝。
sudo apt update
安裝ASP.NET Core運(yùn)行時(shí) 由于我們是部署應(yīng)用,只需在服務(wù)器上安裝運(yùn)行時(shí)即可,無需安裝.net sdk
sudo apt install -y aspnetcore-runtime-6.0
查看是否安裝成功:
dotnet --info
安裝配置 Nginx 安裝Nginx
sudo apt install nginx
編輯Nginx配置文件
vim /etc/nginx/sites-available/default
Esc
進(jìn)入命令模式,gg
跳至首行,然后dG
,清空當(dāng)前配置,復(fù)制粘貼下面的配置。
server { listen 80; server_name example.com *.example.com; location / { proxy_pass http://127.0.0.1:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade ; proxy_set_header Connection keep-alive; proxy_set_header Host $host ; proxy_cache_bypass $http_upgrade ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; proxy_set_header X-Forwarded-Proto $scheme ; } }
退出并且保存 (Esc
+ :wq
,然后回車)
測(cè)試配置是否正確:
sudo nginx -t
沒問題之后,讓Nginx重新加載配置
sudo nginx -s reload
用戶及權(quán)限 創(chuàng)建一個(gè)賬號(hào)等下給Github Actions使用,總不能給它用root賬號(hào)
sudo adduser github
創(chuàng)建一個(gè)文件夾,后面發(fā)布后的文件就上傳到這里
sudo mkdir -p /home/project/example
給新賬號(hào)添加該文件夾的讀寫權(quán)限
sudo chown -R github /home/project/example
到這里其實(shí)可以手動(dòng)上傳發(fā)布文件到服務(wù)器測(cè)試一下,但是為了省時(shí)間還是跳過,直接用Github Actions來發(fā)布。
Github Actions 配置
打開Github倉庫,選擇如下官方提供的.NET工作流進(jìn)入編輯頁面
使用如下配置:
name: ASP.NET Core 6.0 Example build and deploy on: push: branches: [ 'main' ] pull_request: branches: [ 'main' ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup .NET uses: actions/setup-dotnet@v2 with: dotnet-version: 6.0 .x - name: Restore dependencies run: dotnet restore - name: Build package run: dotnet publish ./src/example -c Release -r linux-x64 --self-contained false -o deploy - name: Upload package uses: garygrossgarten/github-action-scp@v0.7.3 with: host: ${{ secrets.REMOTE_HOST }} username: ${{ secrets.REMOTE_USER }} password: ${{ secrets.REMOTE_PWD }} port: 22 local: /home/runner/work/playground/example/deploy/ remote: '/home/project/example/'
當(dāng)main分支有提交或者PR時(shí),發(fā)布就會(huì)觸發(fā);還有幾個(gè)需要說明的地方,
關(guān)于打包,這里指定了 --self-contained false
,是為了減少發(fā)布的dll文件,更多publish命令,可以參考.NET application publishing overview(https://docs.microsoft.com/en-us/dotnet/core/deploying/)
你可能已經(jīng)注意到y(tǒng)ml文件有很多secrets參數(shù),這是在倉庫如下處進(jìn)行配置
REMOTE_HOST
是服務(wù)器地址,REMOTE_USER
就是上面創(chuàng)建新賬號(hào)github
,我這里使用的是 garygrossgarten/github-action-scp(https://github.com/garygrossgarten/github-action-scp) SSH上傳文件到服務(wù)器,更多用法說明,直接參考文檔。
提交yml文件,打開Actions,查看執(zhí)行情況,可以看到已經(jīng)完成了
檢查下服務(wù)器是不是已經(jīng)有發(fā)布文件了
cd /home/project/example ls -l
手動(dòng)運(yùn)行一下,
dotnet example.dll
可以看到,外網(wǎng)已經(jīng)可以訪問了
如果不能訪問,在阿里云控制臺(tái)檢查安全組規(guī)則,是否添加了80端口。
如果還是不能訪問,檢查一下服務(wù)器的防火墻,將80端口添加進(jìn)去。
ufw status ufw allow 80
systemd 守護(hù)進(jìn)程 為了讓服務(wù)在崩潰或者服務(wù)器重啟之后,也能重新運(yùn)行,這里使用systemd來管理我們的服務(wù)。創(chuàng)建服務(wù)定義文件:
sudo nano /etc/systemd/system/dotnet-example.service
使用如下配置,Ctrl
+ X
退出保存。
[Service] WorkingDirectory=/home/project/example ExecStart=/usr/bin/dotnet /home/project/example/example.dll Restart=always # Restart service after 5 seconds if the dotnet service crashes: RestartSec=5 KillSignal=SIGINT SyslogIdentifier=dotnet-example User=root Environment=ASPNETCORE_ENVIRONMENT=Production Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false [Install] WantedBy=multi-user.target
服務(wù)啟用、啟動(dòng)、查看狀態(tài):
sudo systemctl daemon-reloadsudo systemctl enable dotnet -example.servicesudo systemctl start dotnet -example.servicesudo systemctl status dotnet -example.service
最后更新Github Actions,將如下配置添加到末尾,這里使用的是同一個(gè)人的另一個(gè)項(xiàng)目來執(zhí)行遠(yuǎn)程命令garygrossgarten/github-action-ssh(https://github.com/garygrossgarten/github-action-ssh)
- name: Restart dotnet-example.service uses: garygrossgarten/github-action-ssh@v0.6.3 with: command : sudo systemctl restart dotnet-example.service; cd /home/project/example; ls -l host: ${{ secrets.REMOTE_HOST } } username: ${{ secrets.REMOTE_USER } } password: ${{ secrets.REMOTE_PWD } }
配置生效,發(fā)布成功:
總結(jié) 本文完整介紹了如何使用Github Actions做CI&CD,將ASP.NET Core 6.0 程序部署到阿里云Ubantu服務(wù)器,并使用Nginx作為web服務(wù)器,systemd做守護(hù)進(jìn)程。
雖然現(xiàn)在k8s已經(jīng)很普及,并且很多公司都基本有專門DevOps團(tuán)隊(duì)維護(hù)CI&CD,程序員只需專注業(yè)務(wù)代碼開發(fā)。但是了解并實(shí)操一遍整個(gè)過程還是很有益處的,特別是對(duì)新手。很多未知的坑,實(shí)踐之前你永遠(yuǎn)不知道。就像以前也不知道寫博客還挺累。
感嘆一下,免費(fèi)的Github Actions太良心了,很方便個(gè)人項(xiàng)目或者私活,你完全可以只準(zhǔn)備應(yīng)用服務(wù)器。