在本教學課程中,您將瞭解如何使用 Docker 將 .NET 應用程式容器化。 容器有許多功能和優點,例如不可變的基礎結構、提供可攜式架構,以及啟用延展性。 映像可用來為您的本機開發環境、私人雲端,或公用雲端建立容器。
在本教學課程中,您已:
建立和發佈簡單的 .NET 應用程式
建立及設定適用于 .NET 的 Dockerfile
建置 Docker 映像
建立及執行 Docker 容器
您將瞭解 .NET 應用程式的 Docker 容器建置和部署工作。 「Docker 平台」
會使用「Docker 引擎」
快速建置應用程式,並將其封裝為「Docker 映像」
。 這些映像是以
Dockerfile
格式所撰寫,可在分層式容器中部署及執行。
本教學課程
不適用於
ASP.NET Core 應用程式。 如果您使用 ASP.NET Core,請參閱
瞭解如何容器化 ASP.NET Core 應用程式
教學課程。
安裝下列先決條件:
.NET SDK
如果您已安裝 .NET,請使用
dotnet --info
命令來判斷您使用的 SDK。
Docker Community Edition
Dockerfile
和 .NET 範例應用程式的暫存工作資料夾
。 在本教學課程中,docker-working
名稱
會當做工作資料夾使用。
建立 .NET 應用程式
您需要 Docker 容器將執行的 .NET 應用程式。 開啟您的終端機,建立工作資料夾 (如果沒有),並進入該資料夾。 在工作資料夾中,執行下列命令,在名為
App
的子目錄中建立新專案:
dotnet new console -o App -n DotNet.Docker
您的資料夾樹狀目錄會如下所示:
📁 docker-working
└──📂 App
├──DotNet.Docker.csproj
├──Program.cs
└──📂 obj
├── DotNet.Docker.csproj.nuget.dgspec.json
├── DotNet.Docker.csproj.nuget.g.props
├── DotNet.Docker.csproj.nuget.g.targets
├── project.assets.json
└── project.nuget.cache
此命令 dotnet new
會建立名為 App 的新資料夾,並產生 「Hello World」 主控台應用程式。 從終端機會話變更目錄並流覽至 [應用程式 ] 資料夾。 dotnet run
使用 命令啟動應用程式。 應用程式將會執行,並在命令下方列印 Hello World!
:
cd App
dotnet run
Hello World!
預設範本會建立列印至終端機的應用程式,然後立即終止。 針對此教學課程,您將使用無限期執行迴圈的應用程式。 在文字編輯器中開啟 Program.cs 檔案。
如果您使用 Visual Studio Code,請從上一個終端機會話輸入下列命令:
code .
這會開啟 包含 Visual Studio Code 中專案的應用程式資料夾。
Program.cs 看起來應該像下列 C# 程式碼:
Console.WriteLine("Hello World!");
使用下列每秒計算數字的程式碼來取代檔案:
var counter = 0;
var max = args.Length is not 0 ? Convert.ToInt32(args[0]) : -1;
while (max is -1 || counter < max)
Console.WriteLine($"Counter: {++counter}");
await Task.Delay(TimeSpan.FromMilliseconds(1_000));
儲存檔案,然後使用 dotnet run
再次測試程式。 請記住此應用程式會無限期執行。 使用 cancel 命令 Ctrl+C 來停止它。 以下是範例輸出:
dotnet run
Counter: 1
Counter: 2
Counter: 3
Counter: 4
如果您在命令列上傳遞一個數字給應用程式,它將只會計算到該數量,然後結束。 搭配 dotnet run -- 5
試用它以計算到五。
--
之後的任何參數都不會傳遞至 dotnet run
命令,而會改為傳遞至您的應用程式。
發佈 .NET 應用程式
將 .NET 應用程式新增至 Docker 映射之前,必須先發佈它。 最好讓容器執行已發佈的應用程式版本。 若要發佈應用程式,請執行下列命令:
dotnet publish -c Release
此命令會將您的應用程式編譯至 publish 資料夾。 從工作資料夾通往 publish 資料夾的路徑應該是 .\App\bin\Release\net7.0\publish\
Windows
Linux
dir .\bin\Release\net7.0\publish\
Directory: C:\Users\dapine\App\bin\Release\net7.0\publish
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2/13/2023 1:52 PM 431 DotNet.Docker.deps.json
-a--- 2/13/2023 1:52 PM 6144 DotNet.Docker.dll
-a--- 2/13/2023 1:52 PM 153600 DotNet.Docker.exe
-a--- 2/13/2023 1:52 PM 11052 DotNet.Docker.pdb
-a--- 2/13/2023 1:52 PM 253 DotNet.Docker.runtimeconfig.json
ls
使用 命令來取得目錄清單,並確認已 建立 DotNet.Docker.dll 檔案。
me@DESKTOP:/docker-working/app$ ls bin/Release/net7.0/publish
DotNet.Docker.deps.json DotNet.Docker.dll DotNet.Docker.exe DotNet.Docker.pdb DotNet.Docker.runtimeconfig.json
建立 Dockerfile
docker build
命令會使用 Dockerfile 檔案來建立容器映像。 此檔案是名為 Dockerfile 的文字檔,沒有副檔名。
在包含 .csproj 的目錄中建立名為 Dockerfile 的 檔案,並在文字編輯器中開啟它。 本教學課程將使用 ASP.NET Core 執行時間映射(其中包含 .NET 執行時間映射),並與 .NET 主控台應用程式對應。
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env
WORKDIR /App
# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
ASP.NET Core 執行時間映射是刻意在這裡使用,雖然 mcr.microsoft.com/dotnet/runtime:7.0
可以使用映射。
此 Dockerfile 會使用多階段組建,藉由分層建置,只保留必要的成品,將映射的最終大小優化。 如需詳細資訊,請參閱 Docker Docs:多階段組建 。
關鍵字 FROM
需要完整的 Docker 容器映射名稱。 Microsoft Container Registry (MCR, mcr.microsoft.com) 是 Docker Hub 的 Syndicate,可裝載可公開存取的容器。 區 dotnet
段是容器存放庫,而 sdk
或 aspnet
區段則是容器映射名稱。 映射會以 7.0
標記,用於版本設定。 因此, mcr.microsoft.com/dotnet/aspnet:7.0
是 .NET 7.0 執行時間。 請確定您提取符合 SDK 目標執行時間的執行時間版本。 例如,在上一節中建立的應用程式會使用 .NET 7.0 SDK 和 Dockerfile 中 參考的基底映射加上 7.0 標記。
儲存 Dockerfile 檔案。 工作資料夾的目錄結構應如下所示。 已省略一些更深層次的檔案和資料夾,以節省文章中的空間:
📁 docker-working
└──📂 App
├── Dockerfile
├── DotNet.Docker.csproj
├── Program.cs
├──📂 bin
│ └──📂 Release
│ └──📂 net7.0
│ └──📂 publish
│ ├── DotNet.Docker.deps.json
│ ├── DotNet.Docker.exe
│ ├── DotNet.Docker.dll
│ ├── DotNet.Docker.pdb
│ └── DotNet.Docker.runtimeconfig.json
└──obj 📁
└──...
從終端機執行下列命令:
docker build -t counter-image -f Dockerfile .
Docker 將會處理 Dockerfile 中的每一行。 .
命令中的 docker build
會設定映射的組建內容。 參數 -f
是 Dockerfile 的路徑 。 此命令會建置映射,並建立名為 counter-image 的本機存放庫,指向該映射。 當此命令完成之後,執行 docker images
以查看已安裝的映像清單:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
counter-image latest 2f15637dc1f6 10 minutes ago 208MB
存放 counter-image
庫是映射的名稱。 標記 latest
是用來識別影像的標記。 2f15637dc1f6
是映射識別碼。 10 minutes ago
是建立映射的時間。 208MB
是影像的大小。 Dockerfile 的最後步驟 是從映射建立容器,然後執行應用程式、將已發佈的應用程式複製到容器,以及定義進入點。
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /App
COPY --from=build-env /build/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
COPY
命令會指示 Docker,將您電腦上指定的資料夾複製到容器中的資料夾。 在此範例中 ,publish 資料夾會複製到容器中名為 build 的資料夾。
命令會將 WORKDIR
容器內的目前目錄 變更為 App 。
下一個命令 ENTRYPOINT
會指示 Docker 將容器設定為以可執行檔的形式執行。 當容器啟動時,ENTRYPOINT
命令就會執行。 當此命令結束時,容器將會自動停止。
如需新增的安全性,您可以退出宣告診斷管線。 當您退出宣告時,這可讓容器以唯讀方式執行。 若要這樣做,請將環境變數指定 DOTNET_EnableDiagnostics
為 0
(在步驟之前 ENTRYPOINT
):
ENV DOTNET_EnableDiagnostics=0
如需各種 .NET 環境變數的詳細資訊,請參閱 .NET 環境變數 。
.NET 6 會在前置詞 DOTNET_
上標準化,而不是 COMPlus_
針對設定 .NET 執行時間行為的環境變數。 不過,COMPlus_
前置詞將繼續運作。 如果您使用舊版 .NET 執行時間,您仍應該使用環境變數的 COMPlus_
前置詞。
從終端機中執行 docker build -t counter-image -f Dockerfile .
,並在該命令完成時,執行 docker images
。
docker build -t counter-image -f Dockerfile .
[+] Building 0.2s (14/14) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/aspnet:7.0 0.1s
=> [internal] load metadata for mcr.microsoft.com/dotnet/sdk:7.0 0.1s
=> [build-env 1/5] FROM mcr.microsoft.com/dotnet/sdk:7.0@sha256:80dce5844ecdc719704 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 4.00kB 0.0s
=> [stage-1 1/3] FROM mcr.microsoft.com/dotnet/aspnet:7.0@sha256:8dd65c009a093947cb 0.0s
=> CACHED [stage-1 2/3] WORKDIR /App 0.0s
=> CACHED [build-env 2/5] WORKDIR /App 0.0s
=> CACHED [build-env 3/5] COPY . ./ 0.0s
=> CACHED [build-env 4/5] RUN dotnet restore 0.0s
=> CACHED [build-env 5/5] RUN dotnet publish -c Release -o out 0.0s
=> CACHED [stage-1 3/3] COPY --from=build-env /App/out . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:2094c4692eeaeabebfa2cc68f77907e9ca8455deea948012690c6639 0.0s
=> => naming to docker.io/library/counter-image 0.0s
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
counter-image latest 2094c4692eea About a minute ago 212MB
Dockerfile 中的每個命令都會產生一個圖層,並建立映像識別碼。 最終 的映射識別碼 (您的 將會不同) 是 2f15637dc1f6 ,接下來您將根據此映射建立容器。
您現在已有包含應用程式的映像,您可以建立一個容器。 您可以兩種方式建立容器。 首先,建立已停止的新容器。
docker create --name core-counter counter-image
此命令 docker create
會根據 計數器映射映射 建立容器。 該命令的輸出會顯示 所建立容器的容器識別碼 (您的 將會不同):
d0be06126f7db6dd1cee369d911262a353c9b7fb4829a0c11b4b2eb7b2d429cf
若要查看「所有」容器的清單,請使用 docker ps -a
命令:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d0be06126f7d counter-image "dotnet DotNet.Docke…" 12 seconds ago Created core-counter
容器是以特定名稱 core-counter
建立的,此名稱是用來管理容器。 下列範例會使用 docker start
命令來啟動容器,然後使用 docker ps
命令只顯示正在執行的容器:
docker start core-counter
core-counter
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf01364df453 counter-image "dotnet DotNet.Docke…" 53 seconds ago Up 10 seconds core-counter
同樣地,docker stop
命令將會停止容器。 下列範例會使用 docker stop
命令來停止容器,然後使用 docker ps
命令來顯示未執行任何容器:
docker stop core-counter
core-counter
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
連線到容器
當容器正在執行之後,您可以連線到它以查看輸出。 使用 docker start
和 docker attach
命令來啟動容器,並查看輸出資料流。 在此範例中 ,Ctrl+C 按鍵可用來與執行中的容器中斷連結。 除非另有指定,否則此擊鍵將會結束容器中的進程。 參數 --sig-proxy=false
可確保 Ctrl+C 不會停止容器中的進程。
當您從容器中斷連結之後,請重新連結以確認它仍在執行且正在進行計算。
docker start core-counter
core-counter
docker attach --sig-proxy=false core-counter
Counter: 7
Counter: 8
Counter: 9
docker attach --sig-proxy=false core-counter
Counter: 17
Counter: 18
Counter: 19
在本文中,您不希望容器懸而未執行任何動作。 刪除您先前建立的容器。 如果容器正在執行,請停止它。
docker stop core-counter
下列範例會列出所有容器。 然後,它會使用 docker rm
命令來刪除容器,然後檢查任何執行中容器的第二次。
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f6424a7ddce counter-image "dotnet DotNet.Dock…" 7 minutes ago Exited (143) 20 seconds ago core-counter
docker rm core-counter
core-counter
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Docker 提供 docker run
命令來建立容器,並以單一命令執行。 使用此命令,就不需依序執行 docker create
及 docker start
。 您也可以設定此命令,在容器停止時自動刪除容器。 例如,使用 docker run -it --rm
來執行兩個動作,首先,自動使用目前的終端機連線到容器,然後在容器完成時將其移除:
docker run -it --rm counter-image
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
容器也會將參數傳遞至 .NET 應用程式的執行。 若要指示 .NET 應用程式只計算為 3,請傳入 3。
docker run -it --rm counter-image 3
Counter: 1
Counter: 2
Counter: 3
使用 docker run -it
時, Ctrl+C 命令將會停止在容器中執行的進程,接著會停止容器。 由於已提供 --rm
參數,因此會在程序停止時自動刪除容器。 確認它不存在:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
變更 ENTRYPOINT
docker run
命令也可讓您從 Dockerfile 修改 ENTRYPOINT
命令並執行其他動作,但只適用於該容器。 例如,使用下列命令來執行 bash
或 cmd.exe
。 視需要編輯命令。
Windows
Linux
在此範例中,ENTRYPOINT
會變更為 cmd.exe
。 按下 Ctrl+C 以結束進程並停止容器。
docker run -it --rm --entrypoint "cmd.exe" counter-image
Microsoft Windows [Version 10.0.17763.379]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\>dir
Volume in drive C has no label.
Volume Serial Number is 3005-1E84
Directory of C:\
04/09/2019 08:46 AM <DIR> app
03/07/2019 10:25 AM 5,510 License.txt
04/02/2019 01:35 PM <DIR> Program Files
04/09/2019 01:06 PM <DIR> Users
04/02/2019 01:35 PM <DIR> Windows
1 File(s) 5,510 bytes
4 Dir(s) 21,246,517,248 bytes free
C:\>^C
在此範例中,ENTRYPOINT
會變更為 bash
。 執行 exit
命令以結束程序並停止容器。
docker run -it --rm --entrypoint "bash" counter-image
root@9f8de8fbd4a8:/App# ls
DotNet.Docker DotNet.Docker.deps.json DotNet.Docker.dll DotNet.Docker.pdb DotNet.Docker.runtimeconfig.json
root@9f8de8fbd4a8:/App# dotnet DotNet.Docker.dll 7
Counter: 1
Counter: 2
Counter: 3
root@9f8de8fbd4a8:/App# exit
Docker 有許多不同的命令,可建立、管理及與容器和映射互動。 這些 Docker 命令對於管理容器而言非常重要:
docker build
docker run
docker ps
docker stop
docker rm
docker rmi
docker image
在本教學課程中,您已建立容器和映射。 您可以視需要刪除這些資源。 使用下列命令
列出所有容器
docker ps -a
停止依其名稱執行的容器。
docker stop core-counter
docker rm core-counter
接下來,在電腦上刪除您不再需要的任何映像。 刪除 Dockerfile 所建立的映射,然後刪除 Dockerfile 所依據的 .NET 映射。 您可以使用映像識別碼或存放庫:標記格式的字串。
docker rmi counter-image:latest
docker rmi mcr.microsoft.com/dotnet/aspnet:7.0
使用 docker images
命令來查看已安裝的映像清單。
映像檔可能很大。 一般而言,會移除您在測試及開發應用程式時所建立的暫存容器。 如果您打算根據已安裝的執行階段建置其他映像,您通常會使用該執行階段來保存基底映像。
了解如何將 ASP.NET Core 應用程式容器化。
嘗試 ASP.NET Core 微服務教學課程。 \(英文\)
檢閱支援容器的 Azure 服務。
了解 Dockerfile 命令。 \(英文\)
探索 Visual Studio 的容器工具