擷取現有的 Docker 映像並將它部署到本機
Docker 是能讓您快速輕鬆部署應用程式和服務的技術。 Docker 應用程式使用 Docker 映像執行。 Docker 映像是預先封裝的環境,其中包含應用程式程式碼和執行程式碼的環境。
在前文所述的公司案例中,您希望調查使用 Docker 來封裝和執行應用程式的可行性。 您決定要建立和部署執行測試 Web 應用程式的 Docker 映像。
在本單元中,您將了解執行 Docker 映像儲存的容器化應用程式所涉及的重要概念和程序。
Docker 概觀
Docker 是執行容器化應用程式的工具。 容器化應用程式包含應用程式和構成執行環境的檔案系統。 例如,容器化應用程式可能包含資料庫,以及執行應用程式所需的其他相關軟體和設定資訊。
容器化應用程式磁碟使用量通常比設定執行相同應用程式的虛擬機器小。 磁碟使用量較小是因為虛擬機器必須提供整個作業系統和相關的支援環境。 Docker 容器無此額外負荷,因為 Docker 使用主機電腦的作業系統核心為容器提供動能。 下載並啟動 Docker 映像比下載和執行提供類似功能的虛擬機器更為快速,也更符合空間效益。
您建立包含 Docker 所使用一組檔案和設定資訊區段的映像,以建立容器化應用程式。 您可以要求 Docker 啟動以映像為基礎的容器來執行應用程式。 當容器啟動時,Docker 使用映像設定來決定要在容器內執行哪個應用程式。 Docker 提供作業系統資源和必要的安全性。 這可確保容器同時執行,且保持「相對」隔離。
重要
Docker 不提供虛擬機器可用的隔離層級。 虛擬機器在硬體層級實作隔離。 Docker 容器共用基礎作業系統資源和程式庫。 不過,Docker 會確保容器無法存取其他的資源,除非容器設定為如此。
如果您在本機開發和測試,則可以在桌上型電腦或筆記型電腦執行 Docker。 針對生產系統,Docker 可供伺服器環境使用,包括許多 Linux 發行版本與 Microsoft Windows Server 2016。 許多廠商也在雲端支援 Docker。 例如,您可將 Docker 映像儲存在 Azure Container Registry,然後使用 Azure 容器執行個體執行容器。
在本課程模組中,您將在本機使用 Docker 來建立和執行映像。 然後,您會將映像上傳至 Azure Container Registry,並在 Azure 容器執行個體中執行。 本版 Docker 適用於在本機開發和測試 Docker 映像。
Linux 和 Windows Docker 映像
Docker 起初是針對 Linux 開發,之後已擴充為可支援 Windows。 個別的 Docker 映像為 Windows 型或 Linux 型,但不能同時為兩者。 映像的作業系統決定容器內使用何種作業系統環境。
希望在 Linux 型和 Windows 型映像中提供相似功能的 Docker 映像作者,可以分別建立這些映像。 例如,Microsoft 提供的 Windows 和 Linux Docker 映像包含 ASP.NET Core 環境,可用作容器化 ASP.NET Core 應用程式的基礎。
已安裝 Docker 的 Linux 電腦只能執行 Linux 容器。 已安裝 Docker 的 Windows 電腦則可執行兩種容器。 Windows 使用虛擬機器執行 Linux 系統,並使用虛擬 Linux 系統執行 Linux 容器,所以兩者都可執行。
在本課程模組中,您將建立和執行 Linux 型映像。
Docker 登錄和 Docker Hub
Docker 映像儲存在「登錄」中可供使用。 登錄是 Docker 可以連線來上傳和下載容器映像的 Web 服務。 最為人熟知的登錄是 Docker Hub,這是公用登錄。 許多個人和組織都會將映像發佈至 Docker Hub,您可以使用在桌上型電腦、伺服器或雲端中執行的 Docker 下載並執行這些映像。 您可以在那裡免費建立 Docker Hub 帳戶和上傳映像。
登錄會組織成一系列的「存放庫」。 每個存放庫包含多個 Docker 映像,有共同的名稱,通常還有相同的用途和功能。 這些映像通常有以標籤識別的不同版本。 基於相容性理由,此機制可讓您發佈及保留多個版本的映像。 當您下載並執行某個映像時,您必須指定登錄、存放庫和映像的版本標籤。 標籤是文字標籤,您可以使用自己的版本編號系統 (v1.0、v1.1、v1.2、v2.0 等)。
假設您想要使用 ASP.NET Core 執行時間 Docker 映像。 此映像提供兩種版本:
- 8.0 (長期支援):
mcr.microsoft.com/dotnet/aspnet:8.0
- 6.0 (長期支援):
mcr.microsoft.com/dotnet/aspnet:6.0
現在,我們假設您想要使用 .NET Core 範例 Docker 映像。 我們有四個版本可以選擇:
mcr.microsoft.com/dotnet/samples:dotnetapp
mcr.microsoft.com/dotnet/samples:dotnetapp-chiseled
mcr.microsoft.com/dotnet/samples:aspnetapp
mcr.microsoft.com/dotnet/samples:aspnetapp-chiseled
注意
單一映像可獲指派多個標籤。 依照慣例,最新版本映像除了有描述版本號碼的標籤外,還獲指派 latest 標籤。 當您發行映像的新版本時,您可以重新指派 latest 標籤以參考新的映像。
存放庫也是映像的隱私權單位。 如果不想共用映像,您可以將存放庫設為私人。 對於您想分享映像的其他使用者,您可以授與存取權。
瀏覽 Docker Hub 和提取映像
注意
您不需要完成任何的範例,或執行下列各節中的任何程式碼。 您將在下一個單元中執行此作業。
您在 Docker Hub 中通常會發現一個映像很符合您要容器化的應用程式類型。 您可以下載此映像,並使用您自己的應用程式程式碼加以擴充。
Docker Hub 包含數千個映像。 您可以從命令列或 Docker Hub 網站,使用 Docker 來搜尋和瀏覽登錄。 網站可讓您依類型和發行者來搜尋、篩選及選取映像。 下圖顯示搜尋頁面的範例。
您可以使用 docker pull
命令搭配映像名稱來擷取映像。 如果您僅指定存放庫名稱,Docker 預設從 Docker Hub 上的該存放庫下載標示為 latest
的映像。 請記住,您可以修改命令以從不同的存放庫提取不同標籤。 此範例從 mcr.microsoft.com/dotnet/samples:aspnetapp 存放庫擷取標籤為 aspnetapp
的映像。 此映像包含簡單的 ASP.NET Core Web 應用程式。
注意
本單元中的範例旨在顯示各種 Docker 命令的語法。 您在閱讀本單元時不需要執行這些命令。 本單元後面的練習會引導您直接使用 Docker。
docker pull mcr.microsoft.com/dotnet/samples:aspnetapp
當您擷取映像時,Docker 會將映像儲存在本機,並提供來執行容器。 您可以使用 docker image list 命令在本機登錄中檢視這些映像。
docker image list
輸出看起來會像下列範例這樣:
REPOSITORY TAG IMAGE ID CREATED SIZE
mcr.microsoft.com/dotnet/samples aspnetapp 6e2737d83726 6 days ago 263MB
在許多其他 Docker 命令中,您可以使用映像名稱識別碼來參考映像。
執行 Docker 容器
使用 docker run
命令來啟動容器。 以名稱或識別碼指定要執行的映像。 如果尚未對映像執行 docker pull
,Docker 會替您代勞。
docker run mcr.microsoft.com/dotnet/samples:aspnetapp
在本範例中,命令回應下列訊息:
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {d8e1e1ea-126a-4383-add9-d9ab0b56520d} may be persisted to storage in unencrypted form.
Hosting environment: Production
Content root path: /app
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.
此映像包含 Web 應用程式,所以它正在接聽抵達 HTTP 連接埠 80 的要求。 不過,如果您開啟網頁瀏覽器並瀏覽至 http://localhost:80
,則不會看到此應用程式。
Docker 預設不允許輸入網路要求到達容器。 您需要將 -p
選項新增至 docker run
,以告知 Docker 將您電腦中的特定連接埠號碼,指派給容器中的特定連接埠號碼。 此指示支援在指定的連接埠上向容器發出網路要求。
此外,此映像中的 Web 應用程式不是從命令列互動使用。 當我們啟動它時,我們希望 Docker 在背景中啟動它並讓它執行。 使用 -d
旗標以指示 Docker 在背景啟動 Web 應用程式。
按下 Ctrl-C 停止映像,然後重新啟動,如下列範例所示:
docker run -p 8080:80 -d mcr.microsoft.com/dotnet/samples:aspnetapp
該命令將容器中的連接埠 80 對應至您電腦上的連接埠 8080。 如果您在瀏覽器中前往頁面 http://localhost:8080
,您會看到範例 Web 應用程式。
容器和檔案
如果執行中容器變更其映像中的檔案,則這些變更只存在於做出變更的容器中。 除非您採取特定的步驟來保留容器狀態,否則移除容器後就會遺失這些變更。 同樣地,以相同映像為基礎的多個容器同時執行時,不共用映像中的檔案。 每個容器都有自己的獨立複本。 容器看不到彼此寫入檔案系統的資料。
您可在容器中新增可寫入的磁碟區。 磁碟區代表容器可裝載的檔案系統,可提供容器中執行的應用程式使用。 當容器停止時,磁碟區中的資料繼續存在,而多個容器可以共用相同的磁碟區。 建立和使用磁碟區的詳細資料不在本課程模組的討論範圍內。
最佳做法是避免需要對 Docker 部署的應用程式變更檔案系統。 請僅將其用於可允許遺失的暫存檔案。
管理 Docker 容器
您可以使用 docker ps
命令檢視作用中的容器。
docker ps
輸出包含容器的狀態 (如果正在執行則為 Up,如果已經終止則為 Exited) 和其他值,例如映像啟動時指定的命令列旗標,以及其他資訊。 Docker 可讓您從同一映像同時執行多個容器,因此每個容器都獲指派唯一的識別碼,以及人們看得懂的唯一名稱。 大部分用來管理個別容器的 Docker 命令,都可以使用識別碼或名稱來參考特定的容器。
在下列輸出中,您可以看到兩個容器。 PORTS 欄位顯示的容器,其識別碼為 elegant_ramanujan
,是正在 Docker 主機連接埠 80 上執行的映像,對應至您電腦的連接埠 8080。 youthful_heisenberg
執行個體是上一次執行映像的容器。 COMMAND 欄位顯示容器為了啟動映像中的應用程式而執行的命令。 在本例中,對兩個容器而言都是 dotnet aspnetapp.dll。 因為兩個容器都執行同一個映像,容器的映像識別碼也相同。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57b9587583e3 mcr.microsoft.com/dotnet/core/samples:aspnetapp "dotnet aspnetapp.dll" 42 seconds ago Up 41 seconds 0.0.0.0:8080->80/tcp elegant_ramanujan
d27071f3ca27 mcr.microsoft.com/dotnet/core/samples:aspnetapp "dotnet aspnetapp.dll" 5 minutes ago Up 5 minutes 0.0.0.0:8081->80/tcp youthful_heisenberg
注意
docker ps
是 docker container ls
的捷徑。 這些命令的名稱是以 Linux 公用程式 ps
和 ls
為基礎,分別列出執行的程序和檔案。
您可以使用 docker stop
命令停止使用中容器,指定容器識別碼。
docker stop elegant_ramanujan
如果再次執行 docker ps
,您會看到輸出中不再顯示 elegant_ramanujan 容器。 容器仍然存在,但不再裝載執行中處理序。 只要加上 -a
旗標,docker ps
的輸出就會包含已停止的容器:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57b9587583e3 mcr.microsoft.com/dotnet/core/samples:aspnetapp "dotnet aspnetapp.dll" 2 minutes ago Exited (0) 21 seconds ago elegant_ramanujan
d27071f3ca27 mcr.microsoft.com/dotnet/core/samples:aspnetapp "dotnet aspnetapp.dll" 7 minutes ago Up 7 minutes 0.0.0.0:8081->80/tcp youthful_heisenberg
您可以使用 docker start
命令重新啟動已停止的容器。 容器的主處理序會重新啟動。
docker start elegant_ramanujan
通常,容器一旦停止,您應該也將其移除。 移除容器會清除任何遺留的資源。 一旦移除容器,在映像檔案系統內所做的任何變更就永久遺失。
docker rm elegant_ramanujan
您無法移除正在執行的容器,但可以在 docker rm
命令中加上 -f 旗標,以強制停止並移除容器。 這是快速停止並移除容器的方式,但應該只在容器內的應用程式不需要執行正常關閉時才使用。
docker container rm -f elegant_ramanujan
移除 Docker 映像
您可以使用 docker image rm
命令從本機電腦中移除映像。 指定要移除之映像的映像識別碼。 下列範例移除範例 Web 應用程式的映像。
docker image rm mcr.microsoft.com/dotnet/core/samples:aspnetapp
必須先終止執行映像的容器,才能移除該映像。 如果仍有容器使用該映像,您會收到類似如下的錯誤訊息。 在此範例中,發生錯誤的原因是 youthful_heisenberg 容器仍在使用該映像。
Error response from daemon: conflict: unable to delete 575d85b4a69b (cannot be forced) - image is being used by running container c13165988cfe