本文簡介
最近在開發一個管理系統,代碼框架是用的前後臺分離的方式
後臺使用的是Asp.Net Core平臺,開發所有業務,向前臺提供Rest API接口。
使用的認證方式是JWT
前端有兩個項目,一個是Web端,一個是Mobild端
都是使用Vue + Ant Design of Vue架構
後端的開發工具使用的是Visual Studio 2019
前端的開發工具使用的是Visual Studio Code
在這前我也寫過通過PowerShell自動部署Asp.Net Core程序到Windows服務器
並使用IIS向外提供服務。
爲了使項目實現運行在全開源平臺,實現低成本、安全、高可用的目的
所以寫這個文章以實現自動部署系統至Ubuntu平臺使用Docker對外提供服務
本文章只實現後端接口項目(Rest API)的部署
本文所有自動部署代碼是基於PowerShell
實現目標
- 在Windows平臺自動編譯API接口
- 把編譯生成的文件發佈到Ubuntu服務器
- 在Ubuntu服務器使用Docker對外提供服務
前置條件
- Ubuntu服務器啓用了SSH,並可以使用RSA Key登錄root 參考文檔:Ubuntu系統配置SSH服務
- Ubuntu服務器安裝了PowerShell 參考文檔:使用PowerShell操作Ubuntu
- Ubuntu服務器安裝了Docker 參考文檔:Ubuntu安裝Docker
自動編譯Asp.Net Core Web API接口
#設置代碼目錄和編譯輸出目錄
$CurPath=(Resolve-Path .).Path
$OutputPath=$CurPath+"\bin\publish\"
#清空輸出目錄
Remove-Item -Path $OutputPath -Force -Recurse
#調用dotnet publish命令發佈程序
#參考:https://docs.microsoft.com/zh-cn/dotnet/core/tools/dotnet-publish
Invoke-Command -ScriptBlock {param($o) dotnet publish -o $o -c "Release" --no-self-contained -r linux-arm64 -v m --nologo "05.Coldairarrow.Api.csproj"} -ArgumentList $OutputPath
#壓縮編譯後的發佈文件
$CurDateString=Get-Date -Format "yyyyMMddHHmmss"
#壓縮文件名加上日期,以後追溯
$ZIPFileName="Deploy"+$CurDateString+".zip"
$ZIPFilePath=$CurPath+"\"+$ZIPFileName
$CompressPath=$OutputPath+"*"
#壓縮文件
#Path:壓縮對象,DestinationPath:輸出壓縮文件全路徑
Compress-Archive -Path $CompressPath -DestinationPath $ZIPFilePath
把壓縮後的編譯文件發佈到服務器
#使用RSA Key免密登錄Ubuntu SSH
$Session = New-PSSession -HostName 10.76.20.162 -UserName root -KeyFilePath "C:\Users\Administrator\.ssh\id_rsa"
#設置遠程服務器部署路徑
$RemotePath="/srv/Deploy/"
#複製文件到服務器
Copy-Item $ZIPFilePath -Destination $RemotePath -ToSession $Session
#設置程序部署目錄
$RemoteDestinationPath=$RemotePath+"API/"
$RemoteZipPath=$RemotePath+$ZIPFileName
#清空程序部署目錄
Invoke-Command -Session $Session -ScriptBlock {param($p) Remove-Item -Path $p -Recurse -Force} -ArgumentList $RemoteDestinationPath
#解壓文件到程序部署目錄
Invoke-Command -Session $Session -ScriptBlock {param($p,$dp) Expand-Archive -Path $p -DestinationPath $dp} -ArgumentList $RemoteZipPath,$RemoteDestinationPath
#刪除本的壓縮文件
Remove-Item -Path $ZIPFilePath
Docker對外提供服務
在程序部署目錄配置Dockerfile
#拉取asp.net core鏡像
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
#設置工作目錄
WORKDIR /app
#把服務器文件複製到Docker
COPY . .
#對外開放5000端口
EXPOSE 5000
#啓動API命令
ENTRYPOINT ["dotnet","Coldairarrow.Api.dll"]
構建API鏡像,並啓動新容器
#停止容器
Invoke-Command -Session $Session -ScriptBlock {docker stop api}
#刪除容器
Invoke-Command -Session $Session -ScriptBlock {docker rm api}
#刪除鏡像
Invoke-Command -Session $Session -ScriptBlock {docker rmi api}
#通過Dockerfile構建鏡像
Invoke-Command -Session $Session -ScriptBlock {docker build -t api /srv/Deploy/API}
#啓動新的容器
Invoke-Command -Session $Session -ScriptBlock {docker run -d -p 5000:5000 --name api api}
部署結果
部署成功後,我們在瀏覽器裏打開
http://10.76.20.162:5000/swagger/
就可以看到我們發佈的API接口
源代碼
Write-Host 'Build Starting' -ForegroundColor Yellow
$CurPath=(Resolve-Path .).Path
$OutputPath=$CurPath+"\bin\publish\"
Remove-Item -Path $OutputPath -Force -Recurse
Invoke-Command -ScriptBlock {param($o) dotnet publish -o $o -c "Release" --no-self-contained -r linux-arm64 -v m --nologo "05.Coldairarrow.Api.csproj"} -ArgumentList $OutputPath
Write-Host 'Build Completed' -ForegroundColor Green
Write-Host 'Compress Starting' -ForegroundColor Yellow
$CurDateString=Get-Date -Format "yyyyMMddHHmmss"
$ZIPFileName="Deploy"+$CurDateString+".zip"
$ZIPFilePath=$CurPath+"\"+$ZIPFileName
$CompressPath=$OutputPath+"*"
Compress-Archive -Path $CompressPath -DestinationPath $ZIPFilePath
Write-Host 'Compress Completed' -ForegroundColor Green
Write-Host 'Deploy Starting' -ForegroundColor Yellow
$Session = New-PSSession -HostName 10.76.20.162 -UserName root -KeyFilePath "C:\Users\Administrator\.ssh\id_rsa"
$Session
Write-Host 'Successfully connected to the server' -ForegroundColor Green
Write-Host 'Start copying files to the server' -ForegroundColor Yellow
$RemotePath="/srv/Deploy/"
Copy-Item $ZIPFilePath -Destination $RemotePath -ToSession $Session
Write-Host 'Copy files completed' -ForegroundColor Green
Write-Host 'Start Expand files on the server' -ForegroundColor Yellow
$RemoteDestinationPath=$RemotePath+"API/"
$RemoteZipPath=$RemotePath+$ZIPFileName
Invoke-Command -Session $Session -ScriptBlock {param($p) Remove-Item -Path $p -Recurse -Force} -ArgumentList $RemoteDestinationPath
Invoke-Command -Session $Session -ScriptBlock {param($p,$dp) Expand-Archive -Path $p -DestinationPath $dp} -ArgumentList $RemoteZipPath,$RemoteDestinationPath
$ConfigProductionFile=$RemoteDestinationPath+"appsettings.Production.json"
Invoke-Command -Session $Session -ScriptBlock {param($p) Remove-Item -Path $p -Force} -ArgumentList $ConfigProductionFile
Write-Host 'Expand Completed' -ForegroundColor Green
Write-Host 'Deploy to Docker Starting' -ForegroundColor Yellow
Invoke-Command -Session $Session -ScriptBlock {docker stop api}
Invoke-Command -Session $Session -ScriptBlock {docker rm api}
Invoke-Command -Session $Session -ScriptBlock {docker rmi api}
Invoke-Command -Session $Session -ScriptBlock {docker build -t api /srv/Deploy/API}
Invoke-Command -Session $Session -ScriptBlock {docker run -d -p 5000:5000 --name api api}
Write-Host 'Deploy to Docker Completed' -ForegroundColor Green
Remove-Item -Path $ZIPFilePath
Write-Host 'Deploy Completed' -ForegroundColor Green