10分鐘瞭解Docker,運維和開發視角有什麼不同?

來源:Java後端技術

Docker 是 Golang 編寫的, 自 2013 年推出以來,受到越來越多的開發者的關注。如今Docker無處不在,這是不爭的事實。開發人員都很喜歡它,運維工程師也需要它。他們都需要深入瞭解如何在關鍵業務環境中構建和維護符合生產級別要求的容器化應用,那麼什麼是Docker?運維和開發視角有什麼不同?本文將告訴你答案。


10分鐘瞭解Docker,運維和開發視角有什麼不同?


本文摘自《深入淺出Docker》,就是那本美亞操作系統排名第一的Docker入門書,被業內譽為:“高中生也能讀懂的 Docker入門教程”。

本文從下面兩部分內容講解Docker。

  • 運維(Ops)視角。
  • 開發(Dev)視角。


在運維視角中,主要包括下載鏡像、運行新的容器、登錄新容器、在容器內運行命令,以及銷燬容器。

在開發視角中,更多關注與應用相關的內容。《深入淺出Docker內》會從GitHub拉取一些應用代碼,解釋其中的Dockerfile,將應用容器化,並在容器中運行它們。

通過上面兩部分內容,你可以從整體上理解Docker究竟是什麼,以及主要組件之間是如何相互配合的。推薦讀者對開發和運維兩部分內容都要閱讀

1.1 運維視角

當讀者安裝Docker的時候,會涉及兩個主要組件:Docker客戶端和Docker daemon(有時也被稱為“服務端”或者“引擎”)。

daemon實現了Docker引擎的API。

使用Linux默認安裝時,客戶端與daemon之間的通信是通過本地IPC/UNIX Socket完成的(/var/run/docker.sock);在Windows上是通過名為npipe:////./pipe/docker_engine的管道(pipe)完成的。讀者可以使用docker version命令來檢測客戶端和服務端是否都已經成功運行,並且可以互相通信。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

如果讀者能成功獲取來自客戶端和服務端的響應,那麼可以繼續後面的操作。如果讀者正在使用 Linux,並且服務端返回了異常響應,則可嘗試在命令的前面加上 sudo——sudo docker version。如果加上sudo之後命令正常運行,那麼讀者需要將當前用戶加入到docker用戶組,或者給本書後面的命令都加上sudo前綴。

1.1.1 鏡像

將Docker鏡像理解為一個包含了OS文件系統和應用的對象會很有幫助。如果讀者實際操作過,就會認為與虛擬機模板類似。虛擬機模板本質上是處於關機狀態的虛擬機。在Docker世界中,鏡像實際上等價於未運行的容器。如果讀者是一名開發者,可以將鏡像比作類(Class)。

在Docker主機上運行docker image ls命令。

$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE


如果讀者運行命令環境是剛完成Docker安裝的主機,或者是Play With Docker,那麼Docker主機中應當沒有任何鏡像,命令輸出內容會如上所示。

在Docker主機上獲取鏡像的操作被稱為拉取(pulling)。如果使用Linux,那麼會拉取ubuntu:latest鏡像;如果使用Windows,則會拉取microsoft/powershell:nanoserver鏡像。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

關於鏡像的存儲位置以及鏡像內部構成,本書會在後續的章節中詳細介紹。現在,讀者只需知道鏡像包含了基礎操作系統,以及應用程序運行所需的代碼和依賴包。剛才拉取的ubuntu鏡像有一個精簡版的Ubuntu Linux文件系統,其中包含部分Ubuntu常用工具。而Windows示例中拉取的microsoft/powershell鏡像,則包含了帶有PowerShell的Windows Nano Server操作系統。

如果拉取了如nginx或者microsoft/iis這樣的應用容器,則讀者會得到一個包含操作系統的鏡像,並且在鏡像中還包括了運行Nginx或IIS所需的代碼。

重要的是,Docker的每個鏡像都有自己的唯一ID。用戶可以通過引用鏡像的ID或名稱來使用鏡像。如果用戶選擇使用鏡像ID,通常只需要輸入ID開頭的幾個字符即可——因為ID是唯一的,Docker知道用戶想引用的具體鏡像是哪個。

1.1.2 容器

到目前為止,讀者已經擁有一個拉取到本地的鏡像,可以使用docker container run命令從鏡像來啟動容器。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

仔細觀察上面命令的輸出內容,會注意到每個實例中的提示符都發生了變化。這是因為-it參數會將Shell切換到容器終端——現在已經位於容器內部了!

接下來分析一下docker container run命令。docker container run告訴Docker daemon啟動新的容器。其中-it參數告訴Docker開啟容器的交互模式並將讀者當前的Shell連接到容器終端(在容器章節中會詳細介紹)。接下來,命令告訴Docker,用戶想基於ubuntu:latest鏡像啟動容器(如果用戶使用Windows,則是基於microsoft/powershell:nanoserver鏡像)。最後,命令告訴Docker,用戶想要在容器內部運行哪個進程。對於Linux示例來說是運行Bash Shell,對於Windows示例來說則是運行PowerShell。

在容器內部運行ps命令查看當前正在運行的全部進程。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

Linux容器中僅包含兩個進程。

  • PID 1:代表/bin/bash進程,該進程是通過docker container run命令來通知容器運行的。
  • PID 9:代表ps -elf進程,查看當前運行中進程所使用的命令/程序。


命令輸出中展示的ps -elf進程存在一定的誤導,因為這個程序在ps命令退出後就結束了。這意味著容器內長期運行的進程其實只有/bin/bash。

Windows 容器運行中的進程會更多,這是由 Windows 操作系統工作方式決定的。雖然Windows容器中的進程比Linux容器要多,但與常見的Windows服務器相比,其進程數量卻是明顯偏少的。

按Ctrl-PQ組合鍵,可以在退出容器的同時還保持容器運行。這樣Shell就會返回到Docker主機終端。可以通過查看Shell提示符來確認。

現在讀者已經返回到Docker主機的Shell提示符,再次運行ps命令。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

可以看到與容器相比,Docker主機中運行的進程數要多很多。Windows容器中運行的進程要遠少於Windows主機,Linux容器中的進程數也遠少於Linux主機。

在之前的步驟當中,是使用Ctrl-PQ組合鍵來退出容器的。在容器內部使用該操作可以退出當前容器,但不會殺死容器進程。讀者可以通過docker container ls命令查看系統內全部處於運行狀態的容器。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

上述的輸出顯示只有一個運行中的容器。這就是前面示例中創建的那個容器。輸出中有該容器,證明了容器在退出後依然是運行的。讀者可以看到這個進程是7min之前創建的,並且一直在運行。

1.1.3 連接到運行中的容器

執行docker container exec命令,可以將Shell連接到一個運行中的容器終端。因為之前示例中的容器仍在運行,所以下面的示例會創建到該容器的新連接。

Linux示例如下。

$ docker container exec -it vigilant_borg bash
root@e2b69eeb55cb:/#


示例中的容器名為“vigilant_brog”。讀者環境中的容器名稱會不同,所以請記得將“vigilant_brog”替換為自己Docker主機上運行中的容器名稱或者ID。

Windows示例如下。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

本例中使用的容器為“pensive_hamilton”。同樣,讀者環境中的容器名稱會不同,所以請記得將“pensive_hamilton”替換為自己Docker主機上運行中的容器名稱或者ID。

注意,Shell提示符又發生了變化。此時已登錄到了容器內部。

docker container exec命令的格式是docker container exec <options> <container-name> <command>。在示例中,將本地Shell連接到容器是通過-it參數實現的。本例中使用名稱引用容器,並且告訴Docker運行Bash Shell(在Windows示例中是PowerShell)。使用十六進制ID的方式也可以很容易地引用具體容器。/<command>/<container-name>/<options>

再次使用Ctrl-PQ組合鍵退出容器。

Shell提示符應當退回到Docker主機中。

再次運行docker container ls命令來確認容器仍處於運行狀態。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

1.2 開發視角

容器即應用!

在本節中,會分析一份應用代碼中的Dockerfile並將其容器化,最終以容器的方式運行。相關代碼可從本書配套資源或我的Github主頁中獲取。

本節接下來的內容會基於 Linux 示例進行演示。但其實兩個示例中都容器化了相同的Web 應用代碼,所以步驟也是一樣的。

進入到倉庫文件目錄之下,查看其內容。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

對於Windows示例,讀者需要cd到dotnet-docker-samples\aspnetapp目錄當中。

Linux的示例是一個簡單的Node.js Web應用。Windows示例是一個簡單的ASP.NET Web應用。

每個倉庫中都包含一個名為Dockerfile的文件。Dockerfile是一個純文本文件,其中描述瞭如何將應用構建到Docker鏡像當中。

查看Dockerfile的全部內容。

10分鐘瞭解Docker,運維和開發視角有什麼不同?


Windows示例中的Dockerfile內容會有所不同。但是,這些區別在現階段並不重要。關於Dockerfile的更多細節本書會在接下來的章節中進行詳細介紹。現在,只需要知道Dockerfile的每一行都代表一個用於構建鏡像的指令即可。

使用docker image build命令,根據Dockerfile中的指令來創建新的鏡像。示例中新建的Docker鏡像名為test:latest。

一定要在包含應用代碼和Dockerfile的目錄下執行這些命令。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

{注:}
Windows示例構建可能花費比較長的時間。構建時間長短是由構建過程中要拉取的鏡像大小和複雜度決定的。

一旦構建完成,就可以確認主機上是否存在test:latest鏡像。

10分鐘瞭解Docker,運維和開發視角有什麼不同?


讀者現在已經擁有一個新的Docker鏡像,其中包含了應用程序。

從鏡像啟動容器,並測試應用。

Linux代碼如下。

$ docker container run -d \
--name web1 \
--publish 8080:8080 \
test:latest

打開Web瀏覽器,在地址欄中輸入容器運行所在的Docker主機的DNS名稱或者IP地址,並在後面加上端口號8080。然後就能看到圖4.1的Web頁面。

如果讀者使用的是Windows示例或者Mac版Docker,則需要將地址替換為localhost:8080或者127.0.0.1:8080;如果讀者使用的是Play with Docker,需要單擊終端界面上的8080超鏈接。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

圖1.1 Linux系統測試應用Web界面

Windows代碼如下。

> docker container run -d \
--name web1 \
--publish 8080:80 \
test:latest

打開Web瀏覽器,在地址欄中輸入容器運行所在的Docker主機的DNS名稱或者IP地址,並在後面加上端口號8080,然後就能看到圖4.2的Web頁面。

10分鐘瞭解Docker,運維和開發視角有什麼不同?

圖1.2 Windows系統測試應用Web界面

如果讀者使用的是Windows示例或者Mac版Docker,則可參考上面的規則。

讀者已經成功將應用代碼構建到了Docker鏡像當中,然後以容器的方式啟動該鏡像,這個過程叫作“應用容器化”。

1.3 本文小結

在運維部分,我們下載了Docker鏡像,啟動容器並且登錄到容器內部執行相應的命令,最後停止容器並刪除。

在開發部分,我們完成了簡單應用的容器化過程:從GitHub拉取應用源代碼,並且通過Dockerfile中的指令,將應用代碼構建到鏡像之中。接著運行了該容器化應用。


分享到:


相關文章: