視頻筆記:Docker 特性及其相關工具 - Tom Verelst

https://www.youtube.com/watch?v=heBI7oQvHZUhtml

http://v.qq.com/page/o/8/j/o03134mlm8j.html前端

基本介紹

Docker 很像(但不是)一個輕量級的虛擬機,有本身的shell, namespace, network interface,能夠以root運行東西,有本身的服務和軟件包node

虛擬機有虛擬硬件層和一個運行其上的完整系統。而容器則是直接將進程運行於現有內核上。因此啓動Docker很是輕量級,啓動很是快速。linux

Docker組成部分,簡單來看,分爲三個角色,客戶端、docker 主機、docker registry。
客戶端運行 docker run, build, pull等命令;
docker host 則有一個docker daemon 在運行,它維護着本地的container和image;
docker registry則是集中管理全部image的地方,docker host將從docker registry取得image。git

Docker 文件系統是分層的,這是基於Union FS的概念,在Ubuntu上使用的是aufs,能夠很天然的支持這種概念。而在CentOS/RHEL上則只能使用DeviceMapper去模擬,性能和穩定性以及一些功能會有問題。在 Linux 3.18 之後,可使用 Overlay FS,這也是 Union FS 的實現。docker

Docker 文件系統分層,最底層是 bootfs(kernel),而後是鏡像中的各類層,最後是運行期的容器的層。容器的存儲層在容器中止後,即被廢棄。shell

嚴格來講並非在容器中止後就被銷燬。容器中止後,其存儲層依然附屬於中止掉的容器。若是利用 docker start 將容器啓動後,會發現其內文件系統的變更依然存在。而這種容器存儲層被廢棄的概念則是指另外一個層面的事情。json

容器應當被視爲 immutable 的,所以容器內部的變更應該能夠隨時被拋棄,不但願丟失的變化部分應該存儲於掛載的數據卷中。後端

因此docker的工做流是 docker run, stop, rm, 再次run。每一次run都是從image創建的新鮮的container,因此裏面的內容永遠是image的狀態,而沒有上一次container中的修改。因此從這個工做流程理解,container中的變更被廢棄了。緩存

Docker 1.10 發佈更新了Layer的ID問題,曾經使用的是隨機UUID,可是發生過沖突,並且很難判斷相同UUID的layer究竟是哪一個。因此從1.10開始,將其升級爲密碼學 Hash 值,SHA256。這樣能夠確保其內容統一,並且Image將會更小。在 1.10 之前,Image 和 Layer 基本是一個完整的東西,可是 1.10 以後,因爲使用了 SHA256,Image 和 Layer 能夠分開復用重複的Layer,這樣Image能夠更小。因爲這種變化,若是從 1.10 之前的版本過來,必需要升級全部 images。

Docker 容器文件層會在中止後被廢棄,那麼數據應該存儲於掛載的卷中。而掛載卷能夠是數據卷也能夠是本地文件,注意是「本地」,不可使用NFS, SMB之類的位置進行掛載,這樣Docker會認爲其不安全。若是須要相似的雲存儲,可使用volume的driver,能夠支持AWS S3之類的存儲。

docker run 一個容器,容器能夠定義 EXPOSE 某些端口,而這些端口是容器之間能夠訪問的,而不是從外部訪問,若是須要這些端口暴露於外部,那麼應該用 -p 或 --publish,將該端口發佈於宿主,能夠映射不一樣端口。

Dockerfile, docker build, images, run

Dockerfile 是分步驟的,而每一步都會被緩存,因此從新構建很是快。

ENTRYPOINTCMD 不一樣,通常 ENTRYPOINT 是要運行的命令,而 CMD 則是參數,docker run 後面所跟隨的其實是 CMD,也就是參數。有些鏡像把 ENTRYPOINT 設爲了 sh -c,這樣 CMD 能夠跟 bash 命令和腳本,因此一些人誤覺得 CMD 就是命令。其實它們只是做爲參數送給了 ENTRYPOINT 中指定的 sh -c

基本命令:build, run, stop, start, ps, ps -a, images, rmi
將鏡像push到registry,docker login, docker push

Docker 歷史

Docker 的歷史是和 Linux 內核發佈歷史緊密相關的。

2007年 Linux 發佈內核 2.6.24

有個特性被添加進來,Control Groups(cgroups)。隨後,使用 cgroups 的 Linux Containers (lxc) 發佈。cgroups 是今天 Docker 的基礎。

cgroups ,能夠限制資源使用,設置優先級,會計,控制。

距演講者說,Linux 中的 nice,實際上就是使用 cgroups 中優先級的功能。
https://en.wikipedia.org/wiki/Nice_(Unix)
不過應該不是。

控制的部分包括freezerestart

(這部分的內容演講者講的有些錯誤,我查詢了一下,進行修正。

2013年2月 Linux 發佈了內核 3.8

http://kernelnewbies.org/Linux_3.8#head-fc2604c967c200a26f336942caee2440a2a4099c

此次完整的實現了 namespace 的隔離,包括了 pid, network, hostname, mount pic, user 的namespace。

正是此次發佈構成了Docker的基礎,同年3月份 Docker 項目正式成爲開源項目。最開始基於 lxc,如今抽象出來了 libcontainer,統一接口,下面能夠支持多種容器組合,默認使用的是 runC,不過能夠換。

2014年8月 Linux 發佈了內核 3.16

cgroups 進行了從新設計。 http://lwn.net/Articles/601840/

Docker Networking 中的 overlay network 所依賴的就是此次內核的改進。

2014年12月 Linux發佈了內核 3.18

通過多年的努力,此次終於第一次在內核中加入了 Union FS的實現,此次是 Overlay fs。(Ubuntu中的aufs爭取了好多年,最後做者懶得爭取了,放棄了)。這樣對於紅帽系未來的服務器,也就終於有可能有Union FS可用了。之前只能湊合用 Device Mapper,並且本地loop仍是不適合在生產環境使用的。因此要使用 overlay 存儲層,須要內核在 3.18 以上。

2015年4月 Linux發佈了內核 4.0

docker 1.12 中的 overlay2 存儲層就依賴的是此次的內核對 overlay 驅動的改進。

2016年 Linux 發佈了內核 4.5

更加完全的改造了 cgroups,稱爲 cgroups2,而且承認其已經穩定。
http://kernelnewbies.org/Linux_4.5#head-621383bcd8bc104aed825c9ebc08a0b986690f8a

使用 Docker 的好處

很是容易擴展,因爲全部東西都打包在一個容器裏了,因此部署的時候不須要在服務器上進行安裝了,因此很適合擴展。

Docker 容器是 immutable 的,能夠將其視爲樂高積木,若是哪一個壞了,扔了換個新的,而不是在舊的上面修修補補。

DevOps,開發人員(Dev)只須要考慮容器內的東西便可,而運營人員(Ops)則只需負責容器外部便可。

持續集成(Continuous Integration)

確保全部環境徹底同樣,不會出現「個人機器上沒問題啊」這種狀況。運行、測試都在容器內。

編排(Orchestration)工具

Compose, Machine, Swarm, Networking

Compose

定義運行多容器應用,單機沒問題,多主機還在試驗中。

實例中,值得注意的是,他的目錄結構。docker-compose.yml 在項目根目錄,每一個應用都有本身獨立目錄,以及其目錄下存在 Dockerfile。這種感受更乾淨。(或許在LNMP示例項目中,我不該該把conf都存在於同一個目錄下,而是應該分應用創建目錄,對應的配置放在各自目錄下。)

另外須要注意的是,在僅有幾臺的應用環境下,他依然定義了前端網絡和後端網絡,讓兩個網絡獨立。

在啓動示例的過程當中,Tom Vereist 提到了這個例子寫的很差的一點,在 worker 項目中,它在容器裏使用 maven 對項目進行了構建。這不是一個好的寫法,這會致使maven的安裝,編譯開發工具的安裝、依賴的安裝等等,會產生一個很是大的鏡像。建議的作法是能夠在另外一個容器中構建,把構建後的軟件包拿到運行的容器中安裝使用便可,避免運行時不須要的東西存在於容器中。

Machine

用於建立、管理 docker host,能夠支持多種雲平臺,提供統一的訪問接口。

Swarm

docker 集羣工具,多宿主管理運行。

能夠定義 docker host 的 label。經過 docker daemon 的 --label 設置;經過 docker-machine --engine-label, --label 設置;將 docker host 設置上標籤。而後在運行的時候能夠經過約束標籤,來決定該容器運行於那些 docker host 上。

能夠定義過濾器,包括兩大類,節點(Node)或容器(Container)。節點多是約束、健康程度等;容器能夠是端口、依賴等。

Networking

建立 Overlay network。替代 link (bridge),link 在一些動態環境下使用會有問題。好比一羣容器啓動後,link的某一個節點掛了,從新運行,使用了新的ip,而還在運行的docker使用的仍是舊的ip去聯繫該節點,致使沒法鏈接。因此只可以把全部節點都down掉,而後從新運行。

嘗試了一下,兩個沒有link關係的容器,能夠經過容器IP訪問對方。因此 link 是創建一種識別的辦法,而不是安全上的創建通道的概念。看了一下文檔,提到了 --icc=false 的參數來建立網絡隔離。
https://docs.docker.com/engine/userguide/networking/work-with-networks/#linking-containers-in-user-defined-networks

link (bridge)使用兩種方式傳遞給宿主其link的主機位置,環境變量和/etc/hosts文件。
https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/#communication-across-links

而多宿主環境中,使用 docker network 建立 overlay network,使用link連接主機,則會有一個內置的DNS進行名字的動態維護,再也不使用 /etc/hosts

在Tom 演示 docker swarm 的時候,我發現他和我同樣創建了一個 bash 腳原本啓動創建 docker host。我以爲應該考慮作個工具使用 yaml 描述文件來創建 docker-machine,就像 docker-compose作的那樣。命令行中有太多的重複信息了。

腳本最後是使用 docker network 建立 overlay 網絡,Tom 提到一點,須要指定 --subnet ,不然將沒法連通,特別是跨主機的時候,有的版本有bug,同一個網絡不必定使用同一段IP地址。不過如今這個bug已經修復了,不指定地址跨主機沒問題。

演示 swarm 的過程當中碰到了和我碰到的同樣的問題。在單機環境中,在 docker compose 中可使用 build 來構建鏡像。可是在 swarm 的多宿主環境中,這樣作的結果會致使全部的 service 會扔到同一個 docker host 中去,而若是打算使用多宿主環境(也是爲何要用swarm 的初衷),則必須使用 registry 中的 image。這樣宿主能夠主動去 registry 下載 image。可使用 docker hub 的服務,或者本身架設 registry。

而且不可使用 link 了,而必須使用 自定義network。Tom 說這是因爲一個 link 的bug,如今不知道是否已經解決了,須要試驗。

經過 environment:"constraint:type==frontend" 的形式來指定約束。

Tom 不推薦在生產環境中使用 compose + swarm,由於碰到了太多的問題,他甚至本身還報告了一個bug #2866。

其它工具

Docker Cloud (cloud.docker.com)

建立 node clusters,能夠選擇AWS, Digital Ocean, Azure,Softlayer等幾大雲服務商。而後可使用docker hub上的鏡像進行部署。創建 Stack 須要腳本,很像compose,其實他們應該支持compose腳本更合適,創建service。

Docker Cloud 適合小規模雲的部署。

Kubernetes

由 Google 開發,用 Go 語言寫的。Google 每週用這個運行2百萬個containers。

一個 kubernetes 集羣由 master 和 minions 組成。master 含有 etcd、scheduler;而每一個 minon 含有 kubelet,proxy 和一羣 pod。

CoreOS

不須要安裝 docker,它包含了 linux container。它也使用 etcd,所不一樣的是它每個 host都運行etcd,這樣避免了單點故障。fleetd,很像是網絡多宿主環境下的 systemd,它負責開啓中止分佈在宿主中的服務。

Lattice

Flocker

Docker Security

Container Security

container 自己很安全,因爲 isolation,只使用必要的依賴。
可使用 --security-opt sec comp:xxx.json,來指定安全策略。
Unikernel,能夠很是靈活定製的內核,只選擇所必須的組件使用,其它的都拋棄,信任域更小。

Node Security

如今 docker daemon 必須以 root 運行。如今的受權機制是 all or nothing,或者能夠管理全部 docker,或者徹底沒有權限管理。這點未來可能會改變。

相關文章
相關標籤/搜索