
我們都知道Docker是一個(gè)容器化工具,那么什么是容器呢,Docker和容器有什么關(guān)系,Docker又能解決什么問題呢?
麻煩的環(huán)境配置
軟件開發(fā)最大的麻煩事之一就是環(huán)境配置,在開發(fā)之前我們需要準(zhǔn)備各種運(yùn)行環(huán)境、IDE、輔助工具。就像我們要使用電腦前,先要安裝操作系統(tǒng)一樣。
而一個(gè)可用軟件的交付過程通常包含兩個(gè)部分 - 開發(fā)和維護(hù)。不幸的是,我們很難保證軟件開發(fā)測(cè)試和運(yùn)行維護(hù)階段的軟件能運(yùn)行在一模一樣的環(huán)境下。開發(fā)常說:"It works on my machine",很多時(shí)候我們都要花大量的時(shí)間去配置環(huán)境和教別人配置環(huán)境。
現(xiàn)在的應(yīng)用程序
- 以前的應(yīng)用程序:
- 幾乎都是單塊應(yīng)用: 大系統(tǒng), 多模塊
- 緊耦合: 內(nèi)部調(diào)用
- 不常變更: 需求穩(wěn)定(改動(dòng)成本高)
- 如今的應(yīng)用程序:
- 解耦: 微服務(wù)/異步
- 經(jīng)常變更: 快速迭代
- 動(dòng)態(tài)創(chuàng)建和部署: 服務(wù)化

新架構(gòu)的挑戰(zhàn)
- 多樣化的技術(shù)棧
- 需要?jiǎng)討B(tài)創(chuàng)建機(jī)器
- 很多活動(dòng)組件
- 運(yùn)維人員需要管理復(fù)雜的架構(gòu)
在新的應(yīng)用程序架構(gòu)下,我們部署應(yīng)用的成本大大增加。
不但要搭建不同語言、不同技術(shù)棧適配的運(yùn)行環(huán)境,還要部署到多個(gè)服務(wù)器主機(jī)上;并且這些主機(jī)還可能來自不同地方(公/私有云主機(jī)、物理主機(jī))。
統(tǒng)一的管理
其實(shí)在軟件開發(fā)的過程中我們就思考過類似的問題 - 如何統(tǒng)一的管理我們的代碼包。例如,Maven、Gradle、NPM,我們使用一個(gè)相同的格式(規(guī)范)將我們的代碼劃分成模塊,并使用一套工具去管理他們。在此之后我們不需要重復(fù)的copy代碼、復(fù)制文件,只需要聲明式的引入我們需要的代碼包就可以了。
當(dāng)然,我們希望我們的應(yīng)用部署也能如此簡單。
“容器”


“容器”是一個(gè)黑盒,對(duì)于它的使用者來說:
- 無需關(guān)心里面有什么:只關(guān)注“容器”能做什么
- 有一套工具來管理黑盒:打包、運(yùn)輸、運(yùn)行
- 減少了部署單元的數(shù)量,從而減少了花銷:多個(gè)工具聚集在一個(gè)“容器”內(nèi)
- 更容易管理多個(gè)環(huán)境:以“容器”為單位進(jìn)行部署和管理
虛擬化技術(shù)
-
虛擬機(jī)
-
精心配置的虛擬機(jī)也是滿足我們(基本)要求的容器,我們能夠通過虛擬機(jī)鏡像來打包我們的應(yīng)用。但是,龐大的操作系統(tǒng)占用了大量的系統(tǒng)資源,使運(yùn)行成本大大上升。
VM.png
-
-
容器
-
(作為進(jìn)程)共用內(nèi)核并提供額外的隔離手段,避免虛擬的操作系統(tǒng)占用。
container.png
-
虛擬機(jī)
- 應(yīng)用
- 運(yùn)行環(huán)境(Java/數(shù)據(jù)庫/libs...)
- 客戶機(jī)操作系統(tǒng)(Guest Operating System)
- 虛擬機(jī)管理系統(tǒng)(Hypervisor)
- 操作系統(tǒng)級(jí):MacOS(HyperKit),Windows的Hyper-V
- 應(yīng)用軟件級(jí):VirtualBox,VMWare Workstation
- 主操作系統(tǒng)(Host Operating System)
- 硬件(Infrastructure)/云主機(jī)
容器
- 應(yīng)用
- 運(yùn)行環(huán)境(Java/數(shù)據(jù)庫/libs...)
- Docker守護(hù)進(jìn)程(Docker Daemon): 類似虛擬機(jī)管理系統(tǒng)
- 主操作系統(tǒng)(Host Operating System)
- 硬件(Infrastructure)/云主機(jī)
容器技術(shù)
容器技術(shù)已經(jīng)發(fā)展了一段時(shí)間了, 例如, LXC, BSD Jails, Solaris Zones...

- 看起來像虛擬機(jī)
- 可以SSH到容器
- 具有root的訪問權(quán)限
- 可以安裝包
- 可以mount文件系統(tǒng)
- 擁有自己的eth0接口
- 可以修改iptables 規(guī)則和routing table
- 共享宿主機(jī)的內(nèi)核
- 隔離 cgroups (memory, cpu, blkio)
- 擁有進(jìn)程空間 (pid, mnt, net, ipc, uts)
- pid - 隔離進(jìn)程PID
- mnt - 允許創(chuàng)建不同的文件系統(tǒng)層級(jí)
- net - 隔離網(wǎng)絡(luò)控制、iptables、防火墻、路由
- ipc - 定義內(nèi)部進(jìn)程交流的范圍
- uts - 允許修改hostname
容器技術(shù)的局限
- 容器沒有標(biāo)準(zhǔn)的格式
- 所以容器是不可移植的
- 沒有標(biāo)準(zhǔn)的工具,所以比如要自己管理網(wǎng)絡(luò)
- 沒有可重用的模塊和API
Docker

- 使容器變得更容易使用
- 容器鏡像的商品化
- 可插拔的模塊易于吸引供應(yīng)商加入
- 適當(dāng)?shù)腁PI可用來創(chuàng)建高層次抽象的工具
- 和微服務(wù)誕生在同一個(gè)時(shí)代
Docker架構(gòu)

- Docker Client:接收命令和Docker Host進(jìn)行交互的客戶端
- Docker Host:運(yùn)行Docker服務(wù)的主機(jī)
- Docker Daemon:守護(hù)進(jìn)程,用于管理所有鏡像和容器
- Docker Images/Containers:鏡像和容器實(shí)例
- Registry(Hub):鏡像倉庫

Docker底層實(shí)現(xiàn)

Docker核心技術(shù)

- Namespace 命名空間
Linux 的命名空間機(jī)制提供了以下七種不同的命名空間,包括CLONE_NEWCGROUP、CLONE_NEWIPC、CLONE_NEWNET、CLONE_NEWNS、CLONE_NEWPID、CLONE_NEWUSER、CLONE_NEWUTS,通過這七個(gè)選項(xiàng)我們能在創(chuàng)建新的進(jìn)程時(shí)設(shè)置新進(jìn)程應(yīng)該在哪些資源上與宿主機(jī)器進(jìn)行隔離。因此容器只能感知內(nèi)部的進(jìn)程,而對(duì)宿主機(jī)和其他容器一無所知。 - CGroups (Control Groups)
Linux 的 CGroup 能夠?yàn)橐唤M進(jìn)程分配資源,也就是我們?cè)谏厦嫣岬降?CPU、內(nèi)存、網(wǎng)絡(luò)帶寬等資源. -
UnionFS
union-fs.png
Docker中的每一個(gè)鏡像都是由一系列的只讀層組成的,Dockerfile 中的每一個(gè)命令都會(huì)在已有的只讀層上創(chuàng)建一個(gè)新的層。通過 docker run 命令可以在鏡像的最上層添加一個(gè)可寫的層 - 容器層,所有對(duì)于運(yùn)行時(shí)容器的修改其實(shí)都是對(duì)這個(gè)容器讀寫層的修改。
容器和鏡像的區(qū)別就在于,所有的鏡像都是只讀的,而每一個(gè)容器其實(shí)等于鏡像加上一個(gè)可讀寫的層,也就是同一個(gè)鏡像可以對(duì)應(yīng)多個(gè)容器。同時(shí)已構(gòu)建的每一層鏡像也可以作為其他鏡像的基礎(chǔ)層進(jìn)行共用。
Docker VS VM



