1. 程式人生 > >Docker系列之AspNetCore Runtime VS .NetCore Runtime VS .NET Core SDK(四)

Docker系列之AspNetCore Runtime VS .NetCore Runtime VS .NET Core SDK(四)

前言

接下來我們就要慢慢步入在.NET Core中使用Docker的殿堂了,在開始之前如題,我們需要搞清楚一些概念,要不然看到官方提供如下一系列映象,我們會一臉懵逼,不知道到底要使用哪一個。

AspNetCore Runtime  VS .NetCore Runtime VS .NET Core SDK 

本節我們所講解的官方所提供的一系列映象都是最新映象,而且閱讀本文的您還需明白一點,要是您看到其他博文中提供的映象以microsoft開頭,那麼說明已過時不再可取。這裡額外再多說一句,很多時候我們看到一些資料,然後親自實踐卻沒達到文章中所描述的效果,大部分情況下可能都是官方已更新導致,一切以官方文件為主才是最佳。我們將官方所提供的映象作如下說明:

映象地址

映象名稱 映象說明

mcr.microsoft.com/dotnet/core/runtime

 .NET Core Runtime 部署.NET Core控制檯程式
mcr.microsoft.com/dotnet/core/runtime-deps 

.NET Core Runtime Dependencies

部署自包含的部署應用程式

mcr.microsoft.com/dotnet/core/sdk 

.NET Core SDK 構建.NET Core(或ASP.NET Core應用程式)

mcr.microsoft.com/dotnet/core/aspnet 

ASP.NET Core Runtime 部署ASP.NET Core應用程式

上述對於.NET Core Runtime Dependencies映象包我沒做過多瞭解,在官方文件上有對這個的詳細介紹名叫《SCD》,送上地址《https://docs.microsoft.com/en-gb/dotnet/core/deploying/index#self-contained-deployments-scd》,搞那麼多包,好像很複雜似的,其實我們只需謹記如下兩點:

若需構建.NET Core應用程式,請使用.NET Core SDK

若需執行.NET Core應用程式,請使用.NET Core Runtime

比如上一節我們構建、釋出應用程式直接在本地進行,所以我們只構建了.NET Core Runtime映象,若在映象中釋出則還需提前下載.NET Core SDK映象,接下來我們執行webapi來說明通過SDK映象來構建程式,Runtime來執行程式。這裡需要注意下,若下載了3.0預覽版本直接執行如下命令所建立的程式版本為3.0,此時可能會因缺少對應包而還原失敗,所以這裡我們將通過命令( dotnet new globaljson --sdk-version 2.2.203 --force )回退到2.2穩定版,繼續往下走。

到這裡為止我們並未如上一節那樣直接釋出,我們將其直接拖到ubuntu中,如下:

這裡針對上一節內容補充說一句(個人有強迫症,上一節建立的映象名稱為(hellowrold),這個映象所打的標籤單詞名稱打錯了,應該是helloworld,所以這裡我們重新命名下映象標籤名稱。又掌握了一個命令,哈哈。首先,我們檢視映象,如下

在Docker中重新命名映象標籤名稱有兩種方式,一是直接通過標籤名稱來重新命名,而是通過映象id來重新命名,如下:

docker tag hellowrold:latest helloworld:latest

或

docker tag 75a287b4f21c helloworld:latest

我們通過如上任何一種方式重新命名後再檢視映象,如下:

因為容器存在對舊映象的引用,所以舊的會仍然存在而不是以新的進行完全覆蓋,所以我們接下來執行如下命令將舊的映象給移除:

docker rmi hellowrold

通過執行如上命令會刪除別名/標籤,由於75a287b4f21c具有其他名稱,因此不會刪除實際影象。

回到正題,接下來我們開始通過Dockerfile來構建webapi映象,如下:

FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
WORKDIR /app

COPY *.csproj ./
RUN dotnet restore

COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
WORKDIR /app

COPY --from=build /app/out .

ENTRYPOINT ["dotnet", "WebApi.dll"]

首先我們構建基礎映象SDK來構建應用程式,我們指定/app作為我們構建的工作目錄。然後將檔案從本地檔案系統複製到映象中,我們將只複製csproj檔案並執行restore,然後複製其他剩餘檔案並執行dotnet publish來構建我們的應用程式併發布。該檔案的執行時部分使用不同的docker基礎映像也就是使用aspnetcore-runtime映像,它複製構建中的所有檔案,然後定義應用程式入口點。我們發現在整個構建映象過程的不同階段都是可互動的,因為如上我們第一階段獲取構建程式映象也就是別名為build,在第二階段獲取執行程式映象也就是runtime,我們引用了build。

從如上我們構建映象命令和上一節對比知道,構建命令可以通過 docker build . -t tagname  或 docker build -t tagname .  這兩種方式來進行皆可。構建映象就是基於上一映象層並建立一個新的映象層的過程,每個新的映象層都對應一個唯一的標識id,我們可以通過如下命令來檢視映象構建的歷史記錄:

docker image history webapi:latest

映象“《none》”說明

當我們構建完映象後,我們檢視映象列表會看到此時會多出了映象標籤名稱為none的,如下:

如上生成的映象none的作用是什麼呢?我們是不是可以將其刪除呢?

優點:它用來維護中間映象層,因為對於每個Dockerfile說明的每一步驟,都會為中間層建立一個新的雜湊值,通過允許快取每個步驟來提高可重用性,減少磁碟使用量並加速docker構建。

缺點:它作為懸空映象,可能會導致磁碟空間問題,但是它被列為docker映象的一部分。(Docker中空的檔案系統層是未使用的,並且沒有被任何映象所引用,因此我們需要一種機制讓Docker清除這些空的映象)

none的映象只是為臨時容器儲存而已,由於Docker的架構,即使容器停止了,這些懸空的映象也依然會保留,所以我們可以對其進行清理,我們可以使用 docker rmi $(docker images -f "dangling=true" -q) 來清理它們,-f "dangling = true" -q顯示所有懸空映象,rmi將刪除所有這些影象,若沒有任何懸空映象但執行了此命令,則會返回錯誤,但是我們可以使用 docker images prune -a (僅適用於1.25以上的docker版本)。

接下來則是建立並啟動容器執行程式,上一節我們在程式碼中配置了埠號為5000,並且也通過 docker run -p 5050:5050 hellowrold 指定相同埠號執行程式,這裡我們在程式碼中並未配置埠,所以預設埠號為80,如下:

docker run webapi:latest

接下來如果我們訪問http:// localhost/api/values,我們會看到無法連線,也就是說沒有得到我們所期望的JSON響應。

這是為何呢?我們來看看docker給我們生成容器的名稱,docker給容器隨機生成例如如下一個名稱:

接下來我們通過終端執行容器管理命令來修復,我們首先將容器停止,然後進行移除,命令如下:

docker container stop gracious_chaplygin
docker container rm gracious_chaplygin

我們需要將gracious_chaplygi替換為從docker container ls返回的容器名稱,我們使用以下命令再次啟動容器:

docker run --name webapi --env ASPNETCORE_ENVIRONMENT=Production -p 80:80 webapi:latest

如上我們配置了3個引數,--name是容器啟動和執行時的名稱,--env允許我們將環境變數傳遞給正在執行的容器,-p允許我們將容器上的埠對映到在我們的機器上的埠。

如上容器已啟動,我們再次使用ls命令檢視我們提供的名稱和埠對映:

上述我猜測可能是因為容器名稱隨機生成的問題,然後指定了容器名稱,結果好使了,但是上述我們再次獲取容器名稱時發現依然是隨機生成的容器名稱,所以我認為不是這個問題導致,和上一節我們執行容器做本節對比,只是指定了對映埠號,而本節未指定埠號,預設啟動埠號為80,容器也執行起來了呀,最終發現還是未指定埠號的緣故,因為當我啟動容器時,也如下明確指定埠號為80就好使了,所以這裡需要注意下。

總結 

本節我們講解了在Docker中安裝對應.NET Core映象包的問題,並且以一個例子來說明,同時呢,我們在上一節使用指令的基礎上又額外添加了對WORKDIR和RUN指令的使用,以及對容器停止、移除、映象列表檢視、映象重新命名、映象刪除、映象構建歷史記錄檢視指令的使用。接下來我們會繼續通過例子來靈活使用各種指令,然後在這個過程中還涉及到一些可優化、以及Docker中比如卷、網路更深入的講解。