Asp.Net Core部署:早知道,還是docker!以及一點碎碎念

語言: CN / TW / HK

前言

AspNetCore技術棧在我們團隊裡的使用也有一段時間了,之前的部署方式一直是本地編譯之後上傳可執行檔案到伺服器,使用supervisor來管理程序這種很原始的方式。

參考之前的文章:https://zhuanlan.zhihu.com/p/203298625

對於小專案來說尚可,夠用,但是存在幾個問題:

  1. 每次更新花費的時間太長了,無論是Framework-Dependent還是Self-Contained,都要上傳很大的檔案~
  2. 更新的時候需要在supervisor裡把程序停掉,不然無法覆蓋
  3. 每次更新都是手動操作,一點也不geek

鑑於之前使用Django的專案裡docker用得非常愉快,而且到處在宣傳.netcore新技術對docker的官方支援有多好多好,於是我這也不能落後,必須上docker部署啊!

更關鍵的一點理由是,最近搞了個新的小專案,用到了Redis,但伺服器上沒裝Redis,作為一個被docker慣壞的人,我也不可能去安裝配置這些東西~

那就開始吧,直接從微軟官方文件開始(MSDN真是好東西啊)

開始

事實上,我現在已經開始嚐鮮使用 .net6.0 來新建專案了,預設的專案模板中就帶有docker配置,完全是傻瓜式的,不用自己寫什麼配置檔案,上傳到伺服器裡就是docker build一把梭(或者是docker-compose up更好)

沒有的也沒事,把VS升級到最新的2022版本~~(其他版本應該也有,請自測)~~,專案右鍵新增就能選擇Docker支援了~

image.png

其實Rider也可以,並且我在此前也是一直使用Rider開發的,但截至本文編寫時,Rider的2021.3版本還沒推出,尚未支援 .net6.0 ,因此我沒有使用Rider測試自動新增docker支援~

image.png

不想使用傻瓜式生成dockerfile也行,下面給出我部署的這個專案的dockerfile,可以參考一下。(專案名稱為:DataMiddlePlatform

```

See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src COPY ["DataMiddlePlatform/DataMiddlePlatform.csproj", "DataMiddlePlatform/"] RUN dotnet restore "DataMiddlePlatform/DataMiddlePlatform.csproj" COPY . . WORKDIR "/src/DataMiddlePlatform" RUN dotnet build "DataMiddlePlatform.csproj" -c Release -o /app/build

FROM build AS publish RUN dotnet publish "DataMiddlePlatform.csproj" -c Release -o /app/publish

FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "DataMiddlePlatform.dll"] ```

其實dockerfile基本可以不管的,因為 .net6.0 專案生成的時候,都會有個dockerfile,在本專案中我只修改了docker-compose.yml檔案,因為要增加一個Redis容器~

以下是我的docker-compose.yml檔案程式碼

```yml version: '3.4'

services: redis: image: redis expose: - 6379

web: image: ${DOCKER_REGISTRY-}web environment: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=https://+:443;http://+:80 build: context: . dockerfile: DataMiddlePlatform/Dockerfile depends_on: - redis ports: - "15002:80" - "15003:443" ```

不多解釋了,docker-compose的用法詳見官方文件~

環境切換

之前我們在docker-compose.yml裡添加了Redis容器,並在web映象裡添加了依賴,所以在Web容器裡訪問Redis是用redis:6379這樣的地址,不像本地開發時一樣使用localhost:6379,如果在Django裡就要在settings.py里根據環境變數判斷了(我的Django-Starter框架集成了自動識別)

而AspNetCore的基礎設施做得很完善,預設就有developmentstagingproduction這三個環境,每個環境有對應的appsettings.json配置檔案,所以只要在配置檔案裡區分不同的Redis地址就好了,如果是其他資料庫的配置也同理,真是方便啊~!

到本專案中就是,在appsettings.Development.json檔案裡,Redis的連線地址是"Connection": "127.0.0.1:6379",本地開發時使用本地安裝的Redis服務。

然後appsettings.json檔案裡,使用"Connection": "redis:6379",docker部署的時候,使用docker裡的Redis服務~

完美

部署

既然寫完了dockerfiledocker-compose.yml,那部署這塊也沒啥好說的,就把整個程式碼資料夾上傳到伺服器,之後一行命令搞定:docker-compose up~

因為這AspNetCore本身效能就很可以了,小專案都不用nginx來提供靜態檔案服務,方便得很~!

要更新服務的話,目前就是上傳程式碼之後執行docker-compose up --build重新構建,因為只需要上傳程式碼檔案,這樣下來每次更新的速度快多了,而且可以寫指令碼在git commit後一鍵執行更新,也…算是自動了吧…hhh

小結

微服務是發展趨勢,應用從舊的部署方式到容器化是很重要的一步,雖然我們團隊的Java還處在一個jar包丟上去supervisor執行的階段,~~(吐槽:後面甚至有專案都沒有掛supervisor,直接shell裡執行起來,什麼時候掛了都不知道)~~

經過這段時間的實踐下來,AspNetCore還是很可靠的扛住了不低的併發,也有比較完善的生態(雖然第三方庫比不上Java和Python,但完完全全夠好用了),開發效率高(但學習門檻也不低,至少比Django難),綜合優缺點下來,加上我自己對這框架的掌握也還很粗淺,所以只能小範圍推廣了~

我對於AspNetCore目前還處在摸索階段,好用是好用,就是在工作中用得還不夠多,不夠熟悉,加上之前折騰Django的經歷讓我嚐到了動態語言開發的甜頭,所以不會短時間把團隊的技術棧全部遷移到NetCore上去,畢竟會C#的人還是不夠多,新招進來的應屆生來現學也有不低的門檻,專案進度也禁不起這種折騰…

我還是很喜歡微軟的這套技術棧,它真的很好用,目前以及後續的小專案毫無疑問都會選擇這套東西,但對於提高多少生產力,我目前是沒多少底氣的,接下來要調研一番構建自動化、部署自動化方面的技術,哎,小團隊的基礎設施不足真是痛苦…… 難怪現在Serverless開始流行起來了,低程式碼平臺也起來了,程式設計師終究要自己砸自己的飯碗…

參考資料