我們已經完成了開發API後,接著我們就需要先用Docker將服務容器化,在那之前我們先解釋一下什麼是Docker,而我們為什麼需要把服務容器化?
容器化技術,是一種虛擬化技術,它允許多個容器共享同一個作業系統核心,這些容器在作業系統層上被隔離運行。
舉例來說:
想像一家餐廳,餐廳的餐桌代表著一台實體主機,每張餐桌上有一個大盤子,這個大盤子就是該主機的作業系統核心。
現在,假設這家餐廳的目標是為客人提供不同種類的食物,而不必為每道菜都提供一個獨立的餐桌(主機)。這就是作業系統層虛擬化的概念。
傳統虛擬化(虛擬機器):如果使用傳統虛擬化技術,每道菜(應用程式)都需要有自己的獨立餐桌(主機)和盤子(作業系統核心)。這意味著每道菜都需要獨立的硬體資源,例如桌子和盤子。
容器化(作業系統層虛擬化):如果使用容器化,多個菜(應用程式)可以共享同一個餐桌(主機),而且它們各自的盤子(容器)放在同一個餐桌上。雖然它們在同一個餐桌上共享空間,但它們是相互隔離的,每道菜都不會影響其他菜的食材。這樣可以節省空間(硬體資源)並實現更高的效率。
容器化技術簡單來說就是,將所有你服務需要的程式碼、套件、執行環境,全部都料理好之後,裝盤就可以上菜了,每個服務都是一道料理。從過去每個服務需要另外準備獨立的作業系統與主機,到現今的每個服務可以共用作業系統與主機。
圖片取自於Docker官方網站
那容器化有什麼好處呢?
以上述的例子來說,容器化之後我們想要換個地方用餐就很方便,將料理打包之後,就可以換到其他地方,使用該地方的餐桌與餐盤,不需要換個地方還要帶著餐桌、餐盤走。
因為作業系統虛擬化,可以共用作業系統核心
1. 未來即使跨系統,也不用再擔心做好的東西,到別人的電腦會不會就壞了。
2. 相較於傳統虛擬機,只有將硬體虛擬化,每台虛擬機都還是要裝作業系統,容器化就輕量許多
還有其他優點我就不一一列出,以上是我比較有感的優點。
再來我們談談什麼是Docker,Docker與容器化技術又有什麼相關聯?
簡單來說Docker就是應用容器化的一個平台,方便我們打包容器、管理容器等等,透過將任何程式打包成可獨立執行的映像檔,發布到任何可執行 Docker 的平台上執行,如此一來,應用程式等於是可以透過 Docker映象檔或甚至只需要 Dockerfile,就能將程式執行環境帶著走,甚至能夠佈置上雲端。
要進入Docker 的世界裡,首先我們有三個主要的概念要認識:
「image」 包裝了一個服務執行,環境所需要的資源,如同上面所說可以任何程式打包成可獨立執行的映像檔,打包帶走,打包完就變成了一個「container」,而「repository」就是存放我們image的地方。
接著我們就要撰寫Dockerfile,撰寫完之後才能夠做成image,我們可以參考官方的寫法
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /<Project Name>
# Restore as distinct layers
COPY ./<Project Name> /<Project Name>
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /<Project Name>
COPY --from=build-env /<Project Name>/out .
ENTRYPOINT ["dotnet", "<Project Name>.dll"]
FROM: 我們使用mcr.microsoft.com/dotnet/sdk:6.0 這個sdk的image作為我們的基本環境
WORKDIR: 在容器內新增一個資料夾
COPY: 複製本機文件到容器資料夾內
RUN: build image 時運行的指令
ENTRYPOINT: run container 固定一定會執行的指令
在打包服務之前,我們需要先將當初var connectionString = builder.Configuration.GetConnectionString("TestDatabase") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
的?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.")
以及app.UseHttpsRedirection();
先去除掉,因為在打包的時候,沒有連接本地資料庫,會發生例外錯誤,後續我們打包完確定除了資料庫沒問題後,會改成公有雲的資料庫服務,然後後者會強制使用https導致無法正常運行。
接著我們可以透過docker build -t <image_name> .
這行指令將Dockerfile build成image,而-t的參數是可以加上tag也可以當成你image的名字,後面沒有指定路徑的話,「.」就是當前目錄搜尋Dockerfile。
build完之後使用docker run -it -p 7242:80 <image_name>
這行指令將image run起來
接著我們就可以到 http://localhost:7242/swagger/index.html 看到服務有在運行,這樣就代表Dockerfile沒有寫錯,run起來後,容器也可以正常執行。
明天我們明天要進入CICD的世界了。
參考資料:
什麼是容器?
作業系統層虛擬化
docker-what is container
10個Q&A快速認識Docker
微軟-建立Dockerfile
微軟-ASP.NET Core 的 Docker 映像(我覺得上面那篇比較好)