docker 學習路線
參考資料
- 知乎 docker 的學習路線
- Docker — 從入門到實踐
- Docker 核心技術與實現原理
- Docker 入門
- 《Kubernetes in Action》,想要學習 Kubernetes 的讀者必定不要錯過。
- 編程能力影響最大的兩本書就是:
- 《計算機程序的構造和解釋》(Structure and Interpertation of Computer Programming,SICP)
- 《計算機程序的概念、技術和模型》(Concepts, Techniques, and Models of Computer Programming,CTMCP)
理解 docker 的核心技術(core tech)
- docker 的核心技術有 namespace, control groups, union filesystem
Namespaces
- 命名空間 (namespaces) 是 Linux 爲咱們提供的用於分離進程樹、網絡接口、掛載點以及進程間通訊等資源的方法。
- Docker 其實就經過 Linux 的 Namespaces 對不一樣的容器實現了隔離。
- Linux 的命名空間機制提供瞭如下七種不一樣的命名空間,包括 CLONE_NEWCGROUP、CLONE_NEWIPC、CLONE_NEWNET、CLONE_NEWNS、CLONE_NEWPID、CLONE_NEWUSER 和 CLONE_NEWUTS,經過這七個選項咱們能在建立新的進程時設置新進程應該在哪些資源上與宿主機器進行隔離。
- Docker 經過命名空間成功完成了與宿主機進程和網絡的隔離。
進程
- 一個是 pid 爲 1 的 /sbin/init 進程
- 負責執行內核的一部分初始化工做和系統配置,也會建立一些相似 getty 的註冊進程。
- 另外一個是 pid 爲 2 的 kthreadd 進程
- 這兩個進程都是被 Linux 中的上帝進程 idle 建立出來的。
- Docker 容器內部的任意進程都對宿主機器的進程一無所知。
- 在 setNamespaces 方法中不只會設置進程相關的命名空間,還會設置與用戶、網絡、IPC 以及 UTS 相關的命名空間。
網絡
- Docker 爲咱們提供了四種不一樣的網絡模式,Host、Container、None 和 Bridge 模式。
- Docker 默認的網絡設置模式:網橋模式。
- 除了分配隔離的網絡命名空間以外,Docker 還會爲全部的容器設置 IP 地址。
- 當 Docker 服務器在主機上啓動以後會建立新的虛擬網橋 docker0,隨後在該主機上啓動的所有服務在默認狀況下都與該網橋相連。
- 在默認狀況下,每個容器在建立時都會建立一對虛擬網卡,兩個虛擬網卡組成了數據的通道,其中一個會放在建立的容器中,會加入到名爲 docker0 網橋中。
- libnetwork:
- 提供了一個鏈接不一樣容器的實現,同時也可以爲應用給出一個可以提供一致的編程接口和網絡層抽象的容器網絡模型。
掛載點
- 新的進程中建立隔離的掛載點命名空間須要在 clone 函數中傳入 CLONE_NEWNS,這樣子進程就能獲得父進程掛載點的拷貝,若是不傳入這個參數子進程對文件系統的讀寫都會同步回父進程以及整個主機的文件系統。
- 若是一個容器須要啓動,那麼它必定須要提供一個根文件系統(rootfs),容器須要使用這個文件系統來建立一個新的進程,全部二進制的執行都必須在這個根文件系統中。
- 爲了保證當前的容器進程沒有辦法訪問宿主機器上其餘目錄,咱們在這裏還須要經過 libcontainer 提供的 pivot_root 或者 chroot 函數改變進程可以訪問文件目錄的根節點。
- chroot 的使用可以改變當前的系統根目錄結構,經過改變當前系統的根目錄,咱們可以限制用戶的權利,在新的根目錄下並不可以訪問舊系統根目錄的結構個文件,也就創建了一個與原系統徹底隔離的目錄結構。
CGroups
- Control Groups(簡稱 CGroups)就是可以隔離宿主機器上的物理資源,例如 CPU、內存、磁盤 I/O 和網絡帶寬。
- 每個 CGroup 都是一組被相同的標準和參數限制的進程,不一樣的 CGroup 之間是有層級關係的,也就是說它們之間能夠從父類繼承一些用於限制資源使用的標準和參數。
- 當咱們使用 Docker 關閉掉正在運行的容器時,Docker 的子控制組對應的文件夾也會被 Docker 進程移除,Docker 在使用 CGroup 時其實也只是作了一些建立文件夾改變文件內容的文件操做,不過 CGroup 的使用也確實解決了咱們限制子容器資源佔用的問題,系統管理員可以爲多個容器合理的分配資源而且不會出現多個容器互相搶佔資源的問題。
- 每個 CGroup 下面都有一個 tasks 文件,其中存儲着屬於當前控制組的全部進程的 pid,做爲負責 cpu 的子系統,cpu.cfs_quota_us 文件中的內容可以對 CPU 的使用做出限制。
UnionFS
- Linux 的命名空間和控制組分別解決了不一樣資源隔離的問題,前者解決了進程、網絡以及文件系統的隔離,後者實現了 CPU、內存等資源的隔離,可是在 Docker 中還有另外一個很是重要的問題須要解決 - 也就是鏡像。
- 使用 docker run 很是輕鬆地從遠程下載 Docker 的鏡像並在本地運行。
- Docker 鏡像其實本質就是一個壓縮包,咱們可使用下面的命令將一個 Docker 鏡像中的文件導出, docker export $(docker create busybox) | tar -C rootfs -xvf -
- Docker 中的每個鏡像都是由一系列只讀的層組成的,Dockerfile 中的每個命令都會在已有的只讀層上建立一個新的層, 當鏡像被 docker run 命令建立時就會在鏡像的最上層添加一個可寫的層,也就是容器層,全部對於運行時容器的修改其實都是對這個容器讀寫層的修改。
- 容器和鏡像的區別就在於,全部的鏡像都是隻讀的,而每個容器其實等於鏡像加上一個可讀寫的層,也就是同一個鏡像能夠對應多個容器。
- AUFS 做爲聯合文件系統,它可以將不一樣文件夾中的層聯合(Union)到了同一個文件夾中,這些文件夾在 AUFS 中稱做分支,整個『聯合』的過程被稱爲聯合掛載(Union Mount)。
- 每個鏡像層或者容器層都是 /var/lib/docker/ 目錄下的一個子文件夾;在 Docker 中,全部鏡像層和容器層的內容都存儲在 /var/lib/docker/aufs/diff/ 目錄中。
- 而 /var/lib/docker/aufs/layers/ 中存儲着鏡像層的元數據,每個文件都保存着鏡像層的元數據,最後的 /var/lib/docker/aufs/mnt/ 包含鏡像或者容器層的掛載點,最終會被 Docker 經過聯合的方式進行組裝。
- Docker 還支持了不一樣的存儲驅動,包括 aufs、devicemapper、overlay二、zfs 和 vfs 等等,在最新的 Docker 中,overlay2 取代了 aufs 成爲了推薦的存儲驅動,可是在沒有 overlay2 驅動的機器上仍然會使用 aufs 做爲 Docker 的默認驅動。
- docker info | grep Storage 查看存儲驅動
- Linux 命名空間、控制組和 UnionFS 三大技術支撐了目前 Docker 的實現,也是 Docker 可以出現的最重要緣由。
docker 基本組件
基本組件(Docker daemon, Docker client, registry鏡像庫, image鏡像,container容器)nginx
- 容器 = 鏡像 + 讀寫層
- 一個倉庫會包含同一個軟件不一樣版本的鏡像,而標籤就經常使用於對應該軟件的各個版本。
- Docker daemon 是服務器組件,以 Linux 後臺服務的方式運行,是 Docker 最核心的後臺進程,咱們也把它稱爲守護進程。它負責響應來自 Docker Client 的請求,而後將這些請求翻譯成系統調用完成容器管理操做。該進程會在後臺啓動一個 API Server ,負責接收由 Docker Client 發送的請求,接收到的請求將經過Docker daemon 內部的一個路由分發調度,由具體的函數來執行請求。
- Docker Client ,也稱 Docker 客戶端。它其實就是 Docker 提供命令行界面 (CLI) 工具,是許多 Docker 用戶與 Docker 進行交互的主要方式。
docker 實踐
- 編寫 Dockerfile 文件,設定 docker 編譯規則
- docker build -t jianglong/nginx_web:v1 . 編譯時設置倉庫名,鏡像名和版本號
- 構建完成以後,使用 docker images 命令查看全部鏡像
- docker run --name nginx_web -d -p 8080:80 jianglong/nginx_web:v1 啓動容器