自動部署Asp.Net Core到Docker
阿新 • • 發佈:2020-08-25
> 原文連結:[個人部落格:自動部署Asp.Net Core至Docker](https://www.giantliu.cn/2020/08/25/200825AutoDeployToDocker/)
## 本文簡介
最近在開發一個管理系統,程式碼框架是用的前後臺分離的方式
後臺使用的是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向外提供服務。
> [使用PowerShell自動編譯部署](https://www.cnblogs.com/liuju150/p/PowerShell-Deploy-Nodejs.html)
為了使專案實現執行在全開源平臺,實現低成本、安全、高可用的目的
所以寫這個文章以實現自動部署系統至Ubuntu平臺使用Docker對外提供服務
> 本文章只實現後端介面專案(Rest API)的部署
> 本文所有自動部署程式碼是基於PowerShell
## 實現目標
1. 在Windows平臺自動編譯API介面
2. 把編譯生成的檔案釋出到Ubuntu伺服器
3. 在Ubuntu伺服器使用Docker對外提供服務
## 前置條件
1. Ubuntu伺服器啟用了SSH,並可以使用RSA Key登入root 參考文件:[Ubuntu系統配置SSH服務](https://www.giantliu.cn/2020/08/24/200824UbuntuSSHConfig/)
2. Ubuntu伺服器安裝了PowerShell 參考文件:[使用PowerShell操作Ubuntu](https://www.giantliu.cn/2020/08/19/InstallPowerShell/)
3. Ubuntu伺服器安裝了Docker 參考文件:[Ubuntu安裝Docker](https://www.giantliu.cn/2020/08/24/200824InstallDockerToUbuntu/)
## 自動編譯Asp.Net Core Web API介面
```powershell
#設定程式碼目錄和編譯輸出目錄
$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
```
## 把壓縮後的編譯檔案釋出到伺服器
```powershell
#使用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
```
![編輯部署](https://img2020.cnblogs.com/blog/45026/202008/45026-20200825124819723-1685907903.png)
## Docker對外提供服務
### 在程式部署目錄配置Dockerfile
```ini
#拉取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映象,並啟動新容器
```powershell
#停止容器
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}
```
![](https://img2020.cnblogs.com/blog/45026/202008/45026-20200825124850087-232416228.png)
## 部署結果
部署成功後,我們在瀏覽器裡開啟
[http://10.76.20.162:5000/swagger/](http://10.76.20.162:5000/swagger/)
就可以看到我們釋出的API介面
![](https://img2020.cnblogs.com/blog/45026/202008/45026-20200825124908596-24433105.png)
## 原始碼
```powershell
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
```