1. 程式人生 > >Docker 學習筆記:Docker簡介和安裝

Docker 學習筆記:Docker簡介和安裝

一、Docker 簡介

Docker 兩個主要部件:

  • Docker: 開源的容器虛擬化平臺
  • Docker Hub: 用於分享、管理 Docker 容器的 Docker SaaS 平臺 -- 
    Docker Hub

Docker 使用客戶端-伺服器 (C/S) 架構模式。Docker 客戶端會與 Docker 守護程序進行通訊。Docker 守護程序會處理複雜繁重的任務,例如建立、執行、釋出你的 Docker 容器。Docker 客戶端和守護程序可以執行在同一個系統上,當然你也可以使用 Docker 客戶端去連線一個遠端的 Docker 守護程序。Docker 客戶端和守護程序之間通過 socket 或者 RESTful API 進行通訊。

非常詳細的 Docker 學習筆記

1.1 Docker 守護程序

如上圖所示,Docker 守護程序執行在一臺主機上。使用者並不直接和守護程序進行互動,而是通過 Docker 客戶端間接和其通訊。

1.2 Docker 客戶端

Docker 客戶端,實際上是 docker 的二進位制程式,是主要的使用者與 Docker 互動方式。它接收使用者指令並且與背後的 Docker 守護程序通訊,如此來回往復。

1.3 Docker 內部

要理解 Docker 內部構建,需要理解以下三種部件:

  • Docker 映象 - Docker images
  • Docker 倉庫 - Docker registeries
  • Docker 容器 - Docker containers

Docker 映象

Docker 映象是 Docker 容器執行時的只讀模板,每一個映象由一系列的層 (layers) 組成。Docker 使用 UnionFS 來將這些層聯合到單獨的映象中。UnionFS 允許獨立檔案系統中的檔案和資料夾(稱之為分支)被透明覆蓋,形成一個單獨連貫的檔案系統。正因為有了這些層的存在,Docker 是如此的輕量。當你改變了一個 Docker 映象,比如升級到某個程式到新的版本,一個新的層會被建立。因此,不用替換整個原先的映象或者重新建立(在使用虛擬機器的時候你可能會這麼做),只是一個新 的層被新增或升級了。現在你不用重新發布整個映象,只需要升級,層使得分發 Docker 映象變得簡單和快速。

Docker 倉庫

Docker 倉庫用來儲存映象,可以理解為程式碼控制中的程式碼倉庫。同樣的,Docker 倉庫也有公有和私有的概念。公有的 Docker 倉庫名字是 Docker Hub。Docker Hub 提供了龐大的映象集合供使用。這些映象可以是自己建立,或者在別人的映象基礎上建立。Docker 倉庫是 Docker 的分發部分。

Docker 容器

Docker 容器和資料夾很類似,一個Docker容器包含了所有的某個應用執行所需要的環境。每一個 Docker 容器都是從 Docker 映象建立的。Docker 容器可以執行、開始、停止、移動和刪除。每一個 Docker 容器都是獨立和安全的應用平臺,Docker 容器是 Docker 的執行部分。

1.4 libcontainer

Docker 從 0.9 版本開始使用 libcontainer 替代 lxc,libcontainer 和 Linux 系統的互動圖如下:

非常詳細的 Docker 學習筆記

1.5 名稱空間「Namespaces」

 pid namespace

不同使用者的程序就是通過 pid namespace 隔離開的,且不同 namespace 中可以有相同 PID。具有以下特徵:

  • 每個 namespace 中的 pid 是有自己的 pid=1 的程序(類似 /sbin/init 程序)
  • 每個 namespace 中的程序只能影響自己的同一個 namespace 或子 namespace 中的程序
  • 因為 /proc 包含正在執行的程序,因此在 container 中的 pseudo-filesystem 的 /proc 目錄只能看到自己 namespace 中的程序
  • 因為 namespace 允許巢狀,父 namespace 可以影響子 namespace 的程序,所以子 namespace 的程序可以在父 namespace 中看到,但是具有不同的 pid

mnt namespace

類似 chroot,將一個程序放到一個特定的目錄執行。mnt namespace 允許不同 namespace 的程序看到的檔案結構不同,這樣每個 namespace 中的程序所看到的檔案目錄就被隔離開了。同 chroot 不同,每個 namespace 中的 container 在 /proc/mounts 的資訊只包含所在 namespace 的 mount point。

net namespace

網路隔離是通過 net namespace 實現的, 每個 net namespace 有獨立的 network devices, IP addresses, IP routing tables, /proc/net 目錄。這樣每個 container 的網路就能隔離開來。 docker 預設採用 veth 的方式將 container 中的虛擬網絡卡同 host 上的一個 docker bridge 連線在一起。

uts namespace

UTS ("UNIX Time-sharing System") namespace 允許每個 container 擁有獨立的 hostname 和 domain name, 使其在網路上可以被視作一個獨立的節點而非 Host 上的一個程序。

ipc namespace

container 中程序互動還是採用 Linux 常見的程序間互動方法 (interprocess communication - IPC), 包括常見的訊號量、訊息佇列和共享記憶體。然而同 VM 不同,container 的程序間互動實際上還是 host 上具有相同 pid namespace 中的程序間互動,因此需要在IPC資源申請時加入 namespace 資訊 - 每個 IPC 資源有一個唯一的 32bit ID。

user namespace

每個 container 可以有不同的 user 和 group id, 也就是說可以以 container 內部的使用者在 container 內部執行程式而非 Host 上的使用者。

有了以上 6 種 namespace 從程序、網路、IPC、檔案系統、UTS 和使用者角度的隔離,一個 container 就可以對外展現出一個獨立計算機的能力,並且不同 container 從 OS 層面實現了隔離。 然而不同 namespace 之間資源還是相互競爭的,仍然需要類似 ulimit 來管理每個 container 所能使用的資源 - cgroup。

Reference

1.6 資源配額「cgroups」

cgroups 實現了對資源的配額和度量。 cgroups 的使用非常簡單,提供類似檔案的介面,在 /cgroup 目錄下新建一個資料夾即可新建一個 group,在此資料夾中新建 task 檔案,並將 pid 寫入該檔案,即可實現對該程序的資源控制。具體的資源配置選項可以在該資料夾中新建子 subsystem ,{子系統字首}.{資源項} 是典型的配置方法, 如 memory.usageinbytes 就定義了該 group 在 subsystem memory 中的一個記憶體限制選項。 另外,cgroups 中的 subsystem 可以隨意組合,一個 subsystem 可以在不同的 group 中,也可以一個 group 包含多個 subsystem - 也就是說一個 subsystem。

  • memory
    • 記憶體相關的限制
  • cpu
    • 在 cgroup 中,並不能像硬體虛擬化方案一樣能夠定義 CPU 能力,但是能夠定義 CPU 輪轉的優先順序,因此具有較高 CPU 優先順序的程序會更可能得到 CPU 運算。 通過將引數寫入 cpu.shares ,即可定義改 cgroup 的 CPU 優先順序 - 這裡是一個相對權重,而非絕對值
  • blkio
    • block IO 相關的統計和限制,byte/operation 統計和限制 (IOPS 等),讀寫速度限制等,但是這裡主要統計的都是同步 IO
  • devices
    • 裝置許可權限制

二、Docker 安裝

docker 的相關安裝方法這裡不作介紹,具體安裝參考  官檔

獲取當前 docker 版本

$ sudo docker version
Client version: 1.3.2
Client API version: 1.15
Go version (client): go1.3.3
Git commit (client): 39fa2fa/1.3.2
OS/Arch (client): linux/amd64
Server version: 1.3.2
Server API version: 1.15
Go version (server): go1.3.3
Git commit (server): 39fa2fa/1.3.2