Note for Docker
前言
最近在學 Docker & Kubernetes,覺得真的是蠻有趣的,想說寫個筆記紀錄一下,也希望可以更去了解它底層的架構、用甚麼技術實現等 …!Docker 官方的文件也是寫的很詳細!推薦大家可以邊看影片邊看官方document~
Docker
Docker當時解決的問題:
在過去開發階段,如果有新的 version 要發行,不同 developer 在測試時,可能會透過他們自己本地的機器或者是 VM 去執行測試。
如果是使用自身的機器的話,開發人員可能有不同的環境、或是package版本的問題,可能有些人是用C#、Java、Ruby、Python開發,那這些環境可能很髒。
像是說 A developer 負責這部分,在他電腦上可以成功順利執行,但是 B deverloper 卻不行執行,這部分可能是因為不同 developer 的 library 版本不同、OS 版本,或者是有 dependency 的衝突產生問題,會導致 bug 的發生,但是這個 bug 的發生卻不是來自於 app 版本裏頭有寫錯的問題,而是因為自身環境。
又或者是使用 VM 去做測試,VM 的創建會耗費掉許多的時間與電腦資源,因為每個 VM 都必須有自己的 Guest OS,這也導致說一台電腦上能安裝的 VM 也是有限的數量,那有沒有比這個更好的方法呢?所以就有 container 的概念被提出。
Container 則是會一起 share host 的 OS,也因此不會占用掉跟 VM 一樣多的資源,像通常一個 VM 應該是以 Gigabytes 來算的,但是 Container 卻是以 Megabytes 來計算的。
並且在雲端的環境中,系統大多都是以 Microservice 作為設計,那就會採用 Container,將我們的 Microservice 放置在各個容器中,打造獨立的執行環境,並且單一 container 所佔的資源小,可減少不必要的資源 (CPU, Memory)的浪費,並且加快啟動速度。
並且如果我們今天需要 Auto-Scaling 的話,自動擴增多個 Container 的成本也大大的小於增加多個 VM。
Container vs VMs:
VM 需要安裝 Hypervisor,像是VMware、Virtual box,再透過Hypervisor去安裝不同的VM,VM是 hardware level 的 virtualization。
Container執行起來更快、更輕。Container是OS level的virtualization。
Container | VM |
---|---|
OS level | hardware level |
seconds | Boost 以 minutes 單位為計算 |
share resources with Host OS | 完全與 Host OS 分離 |
占用少,因為使用 Host OS resources | disk default 會占用很多系統資源 |
containers 通常用完就會被destory | VM 可以很輕鬆地被搬到新的Host上 |
VM的好處
- 安全性較高,因為硬體層以上都虛擬化,因此安全性會相對較高。
- 系統的選擇較多,在VM可以選擇各種不同的OS。
- 應用程式不須要被拆分,因此不需要大幅更改應用程式的架構。簡單來說不需要降低應用程式內服務的耦合性,不需要將程式內的服務個別拆開來部屬。
VM的缺點
- VM的Image大小通常為GB以上,較Container大。
- 啟動速度通常要花個幾分鐘,因此服務重啟的速度較慢。
- 資源使用較多,因為不只給應用程式本身,還要將一部分資源分給VM的作業系統。
Container的好處
- Image較小,通常幾MB。
- 啟動速度較快,通常幾秒就能生成一個Container。
- 因為免去了去在執行一個OS的資源。所以能將更多資源運用在跑服務上。
- 更新較為容易,只需要利用新的Image重新啟動就會更新了。
Container的缺點
- 安全性較VM差,因為環境和硬體都是與本機共用,如果當 Host kernel 出現資安問題了,會影響到所有在電腦上的 containers。
- 在同一台機器中,每個Container的OS都是相同,例如無法一個為windows一個為Linux,還是依賴Host OS。
- Container通常切分成微服務(Microservices)的方式做部署,在各元件中的網路連結會比較複雜。
Container 與 VM 的比較:
- Container 是以 application 為單位,而 VM 是以 OS 為單位。
- Container 依賴 Host OS 的 kernel 來運作 Container,因此 Windows 的 Container 必須在 Windows OS 上運行; Linux Container 必須在 Linux-based OS 上運行,而 VM 則可以隨意選擇。
- Container 的運作不會模擬硬體資源,故相對於 VM,容器並沒有額外運行作業系統 (Guest OS),Container 是一個安裝好 dependency 以及 application 的執行環境,VM 則是配製好 CPU、RAM 與 Storage 的作業系統。
- Container 其實是我們電腦上的一個 process,需要的硬體資源較少,VM 則會占用 CPU、RAM 等硬體資源。
- Container 間是彼此隔離的,因此在同一台機器,可以執行不同版本的服務,VM則會因為版本不同造成衝突。
- VM 較常用於大型服務,Container 多用於 Microservice 中。
Terminology in Docker:
- Images : 像是草稿的概念,我們需要為今天需要提供環境的 application,寫它所需要的環境、dependency等…。
- Container : Image 執行後可以生成 Container,可以想像成草稿變成實體的概念,像是將 server 放在 container 上執行等…。
- Registry : 指我們的 Docker hub,可以從這邊下載 images 到我們的本地端電腦上,也可以上傳我們的Images。
當 Images 開始 run 就會變成 Container,Container其實只是Host OS中的一個process
Docker - Linux Kernel
Docker 透過 Linux Kernel 技術去完成的,因為技術1 & 2讓Container的技術變得可行。
- Cgroups (Control group) 資源分配管理,一台機器跑多個container,記憶體或是 cpu 都是靠Cgroups去完成的。
- Namespace 隔離用的,可以隔離User, 網路, Process等等,因為命名是用string,那原本沒有辦法讓不同OS並存,所以需要namespace,不同container有自己的namespace,各自獨立互不影響。像是 C 中的namespace,原本是為了解決不同的library會有相同的function。
- Union filesystem 權限控管,不同的人像是 root 或是 user 去看file system得到不同的結果,檔案的結構。
Docker for different OS
因為原本的 Docker 是透過 Linux Kernel 去實現的,那平時也是透過 Docker API 去與 Docker Engine 去做互動。
圖片取自: Windows Container 與 Docker是一樣的嗎?
但是後幾年後,為了讓其他的 OS 也可以使用這項技術了,它們做了些微的變化:
Windows 使用虛擬化的技術:
透過 HyperV 安裝 linux 虛擬機做實現
不過近幾年來,Windows 也有推出自己的 Containers:
Mac 透過Virtual box來安裝虛擬機做實現。
致命缺點 of Docker container
Security的問題:可以突破的洞蠻多的。
常見的攻擊,圖片來自:
Docker 可能會遭遇的問題:
- pull 下來的 image 有可能有惡意安裝,如果不小心讓這些 images 在主機上執行,attacker 可以對 container 主機發動攻擊。
- 容器間的溝通也很容易遭到竊聽、攔截,甚至可以直接取得完整系統權限
- Docker 有使用到 Linux Kernel 的技術,像是Namespace,會有機會讓 attacker 可以突破 Namespace 的隔離機制,進一步取得更高的權限。
- 或者是 cgroup,cgroup除了可以對CPU、記憶體資源進行控制,「其中一個特別的功能是建立裝置白名單(Device Whitelist)」
原因:
- 如果當 Attacker 攻擊我們的 Host OS,而 Host OS 又是被所有 Containers share,那即使我們的 Containers 之間的 isolation 還有 安全保護都沒有甚麼用處了。
- 可能會有惡意的人,取名與知名的 image 很像,只要當我們如果打錯字,或者是一不注意就有可能會被 attacker 攻擊。
目前有的解決方法分別是:
- 將VM變得更light weight
- 將container變得更secure
Docker 常用指令
查看目前有的images
|
執行images
|
再run的過程,會檢查是否已經下載過image,如果沒有就會執行 docker pull {image_name}
進入到docker內的terminal
|
-it
interactive terminal
列出目前正在跑的container
|
-a
列出曾經跑過 container 以及 command
查看images 內的內容
|
刪除Container
|
刪除image
|
將 images 上傳至docker hub,或是從遠端 pull 下來
|
Others:docker-compose
可以一次啟動多個container,需要透過 docker-compose.yml
,將所有會使用到的docker images寫下來,也可以互相有連結 ex. frontend & backend & db等
Reference
Docker
Document - Docker run