iT邦幫忙

2022 iThome 鐵人賽

DAY 11
0
自我挑戰組

用 Docker 了嗎? 30 天的 Docker 基本教學系列 第 11

Day 11 Docker Container vs 虛擬機

  • 分享至 

  • xImage
  •  

該文章同步發佈於:我的部落格

也歡迎關注我的 Facebook 以及 Instagram 接收軟體相關的資訊!

以及這個 30 天的 Docker 教學有出書喔!如果喜歡這個系列可以支持一下,天瓏書局

如果你在網路上尋找什麼是容器,常常會看到有人拿容器和虛擬機做比較,這兩項技術在想達成的目的上是有相似之處的,但在眾多相似之處,又有著一些細微的不同。

什麼是虛擬機?

最簡易的說法就是在本身的電腦上透過一個叫做 Hypervisor 的軟體將其作業系統和應用程式與硬體分開來,這樣就可以將自己劃分為數個獨立的「虛擬機器」

可以想像成一個管家 ( Hypervisor ) 幫你把一個房子分隔成好幾間套房,每一個套房都有自己的衛浴設備和供電設施,誰也不求誰,但還是佔掉了整個房子的容積,水龍頭的流水量可能也會因為多條水管牽線而變得不那麼順暢。

每個新的虛擬機器都可以獨立執行自己的作業系統和應用程式,同時還可以分配到從 Hypervisor 管理的原始資源。這些資源包括記憶體、RAM、儲存設備等等,可以看看下方圖片:

容器只是在 Linux 作業系統上的執行程序

下方示範是在 Ubuntu 20.04 的版本上,為了驗證容器在 Linux 系統上只是執行程序。

容器從頭到尾只是在 Linux 作業系統上的執行程序,並不是什麼迷你的虛擬機,它能夠獲取的資源有限,在程序結束時,容器就會進入退出的狀態。

這邊可以用一些方式驗證,到底為什麼說容器本身只是作業系統上的執行程序,我們先啟動一個容器。

$ docker container run --detach --name pg --publish 5432:5432 -e POSTGRES_PASSWORD=password postgres # 不換行
654a8b38709bcb4abbbeea0947dcc50257b350324

接著我們來使用 docker container top 這個指令來查看此容器的執行緒:

$ docker container top pg
UID   PID  PPID  C STIME TTY  TIME     CMD
lxd 50522 50501  0 16:12  ?   00:00:00 postgres
lxd 50604 50522  0 16:12  ?   00:00:00 postgres:checkpointer

docker container top 這個指令的用意在於列出指定容器中的所有執行緒,可以看到裡面有列出 PID 也就是執行緒本身的 ID。

至於要如何驗證容器本身只是一個作業系統上的執行程序呢?我們可以在終端機輸入 ps aux ( 列出系統所有的執行程序資料 )

$ ps aux
USER PID   %CPU %MEM VSZ  RSS  TTY STAT START TIME COMMAND
lxd  50522 0.0  2.6  21.. 26.. ?   Ss   16:12 0:00 postgres
lxd  50604 0.0  0.3  21.. 39.. ?   Ss   16:12 0:00 postgres:checkpointer

這樣我們就可以驗證其實容器本身也是跑在 Linux 的作業系統上,而不是虛擬機的概念,如果是使用虛擬機,在當前的作業系統上是看不到執行緒的。

為什麼只提 Linux 作業系統?

從剛剛到現在一直不斷地強調 Linux 系統,是因為 Windows 以及macOS 上的 Docker 其實是運行在迷你虛擬機上,所以當你輸入 ps aux 是看不到容器的執行程序,這邊也進一步證明了容器本身就是作用在作業系統上的執行程序,所以你沒辦法透過本機的作業系統看到虛擬機內的執行程序。

那要如何在 macOS 上看到容器的執行緒呢?我們需要連接上那迷你的虛擬機,只要按照下方的指令就一樣可以看到虛擬機內的執行程序了:

$ docker run -it --rm --privileged --pid=host justincormack/nsenter1 # 不換行
Unable to find image 'justincormack/nsenter1:latest' locally
latest: Pulling from justincormack/nsenter1
5bc638ae6f98: Pull complete
Digest: sha256:e876f694a4cb6ff9e6861197ea3680fe2e3c5ab773a1e37ca1f13171f7f5798e
Status: Downloaded newer image for justincormack/nsenter1:latest

/# ps aux 
PID   USER    TIME  COMMAND
    1 root    0:02  /sbin/init
    2 root    0:00  [kthreadd]
    3 root    0:00  [rcu_gp]
....(略)
32851 999     0:00 postgres
32938 999     0:00 postgres: checkpointer
32939 999     0:00 postgres: background writer
32940 999     0:00 postgres: walwriter
32941 999     0:00 postgres: autovacuum launcher
32942 999     0:00 postgres: stats collector
32943 999     0:00 postgres: logical replication launcher
.....(略)

/#

透過下方的圖片,我們可以看到安裝虛擬機導致 macOS 以及 Windows 沒辦法直接透過本機來看到容器的執行緒。

macOS 及 Windows 為什麼要安裝虛擬機?

如前面所提,容器是運作在 Linux 上的執行程序,就像你打開一個 App 一樣,但這些容器的執行文件必須建立在其作業系統核心之上。

舉例來說好了,一個為 linux/x86_64 核心打造的 Ruby 映像檔並不會在 Windows上以 ruby.exe 執行,這也是為什麼 Docker 桌面應用程式會需要在macOS 以及 Windows 上面安裝一個迷你的虛擬機。

Docker 從 2013 年到 2016 年,為多種架構 ( amd64、arm/v6、arm/v7、i386等等 ) 建置映像檔,但當時還沒辦法為 Windows 的核心系統建立,所以那時候 Docker 只適用於 Linux。

而在 2016 年,Windows Containers 問世了 ( 偷偷地說,到現在還沒有 macOS Containers )

但說穿了,即使你使用了 WSL 安裝 Ubuntu,也是在執行基於 Linux 的映像檔。

時至今日,Docker 不再只受限於 Linux,當你想到映像檔時,要瞭解到它本身會針對作業系統的核心以及架構進行建置。

Docker 透過 manifest 在後台天衣無縫地完成這些作業,他可以為您所運作的作業系統下載最適合的映像檔,如果你使用 docker container run --platform,就能夠強制使用和你原生作業系統不一樣的映像檔。

小結

今天稍微介紹了一下容器與虛擬機之間的不同,也提到了不同作業系統對於 Docker 的應用情景。

明天將會更加深入容器內部,讓使用容器時能夠更有自信!


上一篇
Day 10 Docker Container 的相關操作指令 ( 下 )
下一篇
Day 12 深入 Docker Container 內部 ( 上 )
系列文
用 Docker 了嗎? 30 天的 Docker 基本教學30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言