Docker Image

我們可以從 DockerHub 中找到 Microsoft 官方的 Images 連結入口。以這次要執行 ASP.NET 程式來說我們可以在這裡找到可以用的 Images。基本上上面都會有簡易的教學要怎麼用,不過琳瑯滿目的 Images 裡面還是有目前相對比較推薦的,像是 Alpine 為基底的 Images 應該是目前佔用空間最小的 Images,當然以此為代價,裡面安裝的工具真的是再基本不過。

ASP.NET Core Install

選擇 .NET Core SDK 來安裝,官方載點。目前版本 3.1 是 LTS 所以我們就選擇這個來裝吧(記得要選 Build Apps,也就是 SDK 來裝,不要選 runtime)。

一旦安裝完畢在 CMD/Power Shell 中就可以使用 dotnet 來操作 dotnet core SDK 了。

可以執行 dotnet --list-sdks 來看看自己目前安裝了哪些 SDK。

我們可以使用 CLI 提供的 new 指令搭配 template 來生成預設的範本,這邊就先使用 asp.net core mvc 當作示範。若需要詳細的 template 種類的話,有官方文件可參考,或可以執行 dotnet new --help 指令來看 new 指令可以有哪些操作,而用 dotnet new --list 來取得目前 SDK 所提供的所有 Template,輸出大致會長以下這樣:

TemplatesShort NameLanguageTags
Console Applicationconsole[C#], F#, VBCommon/Console
Class libraryclasslib[C#], F#, VBCommon/Library
WPF Applicationwpf[C#]Common/WPF
WPF Class librarywpflib[C#]Common/WPF
WPF Custom Control Librarywpfcustomcontrollib[C#]Common/WPF
WPF User Control Librarywpfusercontrollib[C#]Common/WPF
Worker Serviceworker[C#]Common/Worker/Web
Unit Test Projectmstest[C#], F#, VBTest/MSTest
NUnit 3 Test Projectnunit[C#], F#, VBTest/NUnit
NUnit 3 Test Itemnunit-test[C#], F#, VBTest/NUnit
xUnit Test Projectxunit[C#], F#, VBTest/xUnit
ASP.NET Core Emptyweb[C#], F#Web/Empty
ASP.NET Core Web App (Model-View-Controller)mvc[C#], F#Web/MVC
ASP.NET Core Web Appwebapp[C#]Web/MVC/Razor Pages
ASP.NET Core with Angularangular[C#]Web/MVC/SPA
ASP.NET Core with React.jsreact[C#]Web/MVC/SPA
ASP.NET Core with React.js and Reduxreactredux[C#]Web/MVC/SPA
ASP.NET Core Web APIwebapi[C#], F#Web/WebAPI
dotnet gitignore filegitignoreConfig
global.json fileglobaljsonConfig
NuGet ConfignugetconfigConfig
Web ConfigwebconfigConfig
Solution FileslnSolution

選好 template 後可以這樣執行(以 MVC template 為例):

  • dotnet new mvc -n yourProjectName -au Individual 建立好起始專案。
  • dotnet new gitignore 把 dotnet 的 gitignore 檔案給補上。
  • git init 將該專案納入版控。

以這次的範例程式的連結

Develop with Visual Studio Code

若是使用 VS Code 進行開發的話,先安裝好一些 Extensions 在開發時會比較省事:

  • ms-vscode.csharp
  • visualstudioexptteam.vscodeintellicode

基本的應用這兩個應該就可以了。

A Hello World ASP.Net Core Application

要在本機運行先看看成果的話可以在 CLI 執行

dotnet run --project NetCoreTutorial.csproj

或者也可以在 VS Code 裡按下 F5 這個效果也跟以前在 Visual Studio 一樣。基本在執行 dotnet run 時他會去看 Properties 底下的 launchSetting.json 裡面的內容,預設會去抓第一個 "CommandName": "Project" 設定的值,我們在預設的 template 中可以看到他會給兩組值在 profiles 裡,所以我們在執行 dotnet run 時他會第一時間去抓到 NetCoreTutorial 的設定。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"profiles": {
  "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "NetCoreTutorial": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "BenWebApplication":{
      "commandName": "Project",
      "launchBrowser":false,
      "applicationUrl":"https://localhost:5003;http://localhost:5002",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Staging"
      }
    }
}

當然若你有其他設定,你可以用以下指令讓他抓到

dotnet run --launch-profile 'IIS Express'

若是使用範例程式因為還有多墊一層的關係需要多補上 --project 參數變成以下這樣:

dotnet run --launch-profile 'IIS Express' --project .\NetCoreTutorial\NetCoreTutorial.csproj

不過若要使用 IIS 的話需要額外再安裝 Windows Hosting Bundle官網上也有些許說明可以參考。官方上也是有教學文件的,裡面有特別提到使用 IIS 的話可以提供更高的 request throughput ,當然這個 web server 目前是沒有給 Windows 以外的平台執行的版本。

.NET Core Package Management

而套件管理方面已經看不到 packages.config 這個套件管理檔案,取而代之的是 NetCoreTutorial.csproj 裡面 ItemGroup 的 PackageReference。若有新的套件需要加入可以在 CLI 執行以下指令來安裝新的套件

dotnet add package Newtonsoft.Json

若你不知道怎麼把 packages.config 改用 PackageReference 來管理的話,可以看 Official migrate

套件新增語法:

dotnet add <PROJECT> package [選項] <PACKAGE_NAME>

套件移除語法:

dotnet remove <PROJECT> package [選項] <PACKAGE_NAME>

可以在套用的 csproj 中看到異動。

New Package Management Limitation

若使用的是 Visual Studio 2015 或更早的版本來開發,會無法使用 PackageReference,至少需要使用 Visual Studio 2017 或更新的版本來開發。或者…使用 Visual Studio Code 就沒有這個問題了。

Run in Docker

因為我們這次使用到的 Docker Image 只有 runtime environment 所以我們需要在丟進 Container 前就把應用先在本機或是 CI 機器上編譯好,為求簡單我們可以在專案目錄執行以下指令

2020/6/14 補充:其實一般來說跑在 Docker 的應用可以更好的統一編譯環境,會建議即使在 CI 時,也將編譯的動作放在 Container 內執行。所以在正式的程序上都會將 source code 放入存有 SDK 的 container 內然後進行編譯後,再將 artifact 放入只有 runtime 環境的 container 內來執行,這篇文章只是圖方便觀察 artifact 也省下本機資源不要載太多 image 而已。

dotnet publish .\NetCoreTutorial\NetCoreTutorial.csproj --force -c Development -o app

執行完後應該就可以在專案的目錄發現 app 這個資料夾,裡面就會是編譯好的檔案,這也是這次要丟去 Container 的內容。注意,若運行的應用程式需要相依套件以外的設定,像是 hosts 的調整或是執行環境的一些檔案調整之類的就需要在 Dockerfile 裡進行設定。

單純使用 docker 指令也可以把編譯好的檔案放進 container 裡執行,但這樣就會有點手工, Docker 有提供一個方式讓建置 image 的方式可以更好的整合進 CI/CD 流程中。建立一個名稱為 dockerfile 的文字檔在專案的跟目錄下,預設 docker 指令會找這個檔名的檔案來執行,當然也可以利用參數來執行指定的 dockerfile 。

1
2
3
4
5
6
7
# Use an official asp dotnet core 3.1 runtime as a parent image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1.3-alpine3.11
# set working dir in container
WORKDIR /containerApp
# copy host app floder into current location (containerApp)
COPY app ./
ENTRYPOINT ["dotnet", "NetCoreTutorial.dll"]

接下來當前專案根目錄下執行以下指令

docker build -t imageName:v1 .

-t 表示該 image Tag 的名稱,可以直接使用這個名稱來表示 image

. 表示 dockerfile 所在的路徑,預設會找檔名為 dockerfile 的檔案

執行完後執行以下指令應該可以發現 image 多了以下兩個

docker images

docker images

確定我們客製化的 image 順利產生後我們就可以利用以下指令讓該 image 跑在 Container 中。

docker run --rm --name benFirstNetCoreContainer -p 5000:80 imagename:v1

-p 表示 port 的對應,第一個是 host 的 port,第二個是 container 裡的 port

--rm 表示若 container 已存在則自動移除

--name 表示這個 container 的名字,若有給的話之後可以用名字來操作 container,否則的話就只能用 ContainerID

執行以下指令確定 container 有跑起來

docker ps

docker ps

接下來打開 browser 瀏覽以下位置就能看到站台順利跑起來了!

http://localhost:5000/

若想要進入 container 看看執行的執行環境可以找到 ContainerID 後執行以下指令

docker exec -it benFirstNetCoreContainer sh

docker exec

進入 container 後就跟一般的 Linux 執行環境一樣,若要離開 container 直接 exit 就好。

這邊若有在建立 container 時給予名稱的話就可以不用 ID 用名稱來指定 container,而後面的 sh 則是指明進入後要執行的指令,這邊用 sh 主要是因為我們用的是 Alpine 為基底的 image 所以不能用 bash 要用 sh 才行,雖然這個基底附加的東西最少,但相對來講也是最輕量的。

若要停止 container 可以直接 docker stop benFirstNetCoreContainer 就好。

以上就是一個最簡單的 ASP.NET core run in Do

Reference