【轉】Docker那些事(一)

做者:榮幸html

爲何是容器

若是問你如今最熱門的服務器端技術什麼?想必不少人會不假思索的說是容器!node

容器技術實際上並非一個新鮮的名詞,如今你們一提到容器立刻想到的就是Docker,可是容器這個詞並非Docker公司發明的,早期的Pass項目如CloudFoundry,其底層就是基於namespace和cgroups的容器技術。linux

Docker在當時其實是個小弟,並無引發你們的注意,可是如今Docker已經成爲容器事實上的標準,是什麼讓Docker發展成如今這樣的程度呢?docker

這個功能就是Docker鏡像。npm

早期的Pass平臺最爲人詬病的一個軟肋就是應用的打包部署問題,一個應用包在本地部署的好好的,接入Pass平臺後卻問題重重,而Docker鏡像解決了這個根本性問題。json

容器究竟是怎麼回事

前面咱們說了容器其實是很早之前就有的技術,主要用到的是Linux的namespace,cgroups和rootfs。bash

咱們常常說沙盒或者集裝箱,他們裏面裝的是貨物,那容器這個沙盒裝的又是什麼呢?是進程!服務器

咱們把進程裝進一個沙盒(容器)裏面,給他製造邊界,和盒子外面的世界隔離,因此咱們會說容器實際上就是加了圍牆的一個進程。網絡

Namespace

爲進程製造邊界就須要用到namespace技術,咱們先運行一個docker進程看一下:app

docker run -it busybox /bin/sh 
# -it 是提供一個tty的輸入輸出環境
# -d  後臺運行程序
# -v  掛載外部存儲
# -p  端口映射
# -e  參數變量
# busybox 輕量級的容器鏡像

咱們執行ps命令,能夠看到有趣的現象,PID爲1的就是咱們的啓動進程。

clipboard.png

而實際上在宿主機中也會同步啓動一個進程,其PID在宿主機中是22035。

clipboard.png

這就是PID namespace實現的障眼法,它在Linux進程啓動的時候(clone函數),會添加CLONE_NEWPID的參數,進程就會看到一個新的命名空間,因此進程ID就會變成1,實際上進程在宿主機上面仍是22035。

除了PID namespace以外,還有不少的namespace,好比Network、Mount、User等,經過這些namespace對進程進行網絡、儲存、文件等進行限制,使這個進程看不到宿主機的真實狀況,裝在了盒子裏,這就是容器的核心原理了。

Cgroups

咱們經過 Linux 的命名空間爲新建立的進程隔離了文件系統、網絡、宿主機器上的其餘進程,可是命名空間並不可以爲咱們提供物理資源上的隔離,好比 CPU 或者內存。在同一臺機器上可能運行着多個對彼此以及宿主機器一無所知的『容器』,但這些容器卻共同佔用了宿主機器的物理資源。

clipboard.png

若是其中的某一個容器正在執行 CPU 密集型的任務,那麼它就會影響其餘容器的任務執行效率,致使多個容器相互影響而且搶佔資源。如何對多個容器的資源使用進行限制就成了解決進程虛擬資源隔離以後的主要問題,而 Control Group(簡稱 cgroups)就能隔離宿主機器上的物理資源,例如 CPU、內存、磁盤 I/O 和網絡帶寬。cgroups介紹、應用實例及原理描述

容器是一個單進程的模型

經過namespace和cgroups的學習咱們知道了容器就是一個啓用了多個namespace的應用進程,而這個進程可以使用的資源受到cgroups的限制。這裏面有個很重要的概念:容器是一個單進程的模型。

因爲容器本質上面是一個進程,即PID=1的進程,他是後續其餘進程的父進程,這就意味着在一個容器內,你沒有辦法同時運行兩個應用,除非找到一個公共的PID=1的父進程,並使用像systemd或者supervisor這樣的軟件替代PID=1的進程來作爲容器的啓動進程。

可是咱們仍是但願容器和應用是同生命週期的,由於若是容器是好的,而裏面的進程卻已經掛了,這樣處理起來就會很是麻煩了。

經過上面對容器原理的瞭解,咱們能不能分析出容器和虛擬機的區別?

  • 虛擬機須要hypervisor層,在上面建立虛擬機是一個完整的OS
  • 容器是Linux上的一個進程
  • 虛擬機的OS資源消耗比容器大的多
  • 容器使用的是宿主機上相同的內核
  • 容器隔離不了時間等資源

鏡像

前面說了Docker可以成爲容器如今的事實標準,主要是由於Docker創新了鏡像這個東西,那麼鏡像在Linux系統裏面是怎麼存在的呢?

clipboard.png

咱們Docker的工做目錄是/app/docker/docker/ ,其中有個overlay2子目錄,它就是咱們的鏡像目錄。

clipboard.png

咱們在這個目錄下有三個目錄和一個l的目錄,以下:

clipboard.png

咱們能夠進入其中一個目錄,並查看該目錄下diff子目錄的內容:

clipboard.png

到這裏咱們能夠知道,鏡像是由多個層組織並定義的,這些層本質上是文件,這些文件是隻讀的,每層具體的文件存放在層標識符下的diff目錄下。

因此咱們在製做鏡像的時候就須要理解層的概念,提升鏡像製做的效率和重複使用性。

以咱們最常使用的Dockerfile製做鏡像舉例:

FROM node:8.16.0

RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo "Asia/Shanghai" >> /etc/timezone
RUN date -R

RUN mkdir -p /opt/app/
WORKDIR /opt/app

RUN rm -rf /opt/app/node_modules/
COPY package.json ./

RUN npm install --registry=https://registry.npm.taobao.org

Dockerfile 中的每一條命令在最終生成的鏡像中都會產生一層。Docker爲了提升鏡像分發效率,給鏡像賦予了複用層的能力,在拉取,推送,build不一樣鏡像時,不一樣鏡像中內容相同的層能夠被複用從而節省大量操做。

因此咱們應該儘可能把不變的命令放到 Dockerfile 的上層,這樣會顯著提升鏡像的使用效率。


若是但願瞭解更多關於Docker或運維技術的知識,請關注徐徐運維的公衆號
clipboard.png

相關文章
相關標籤/搜索