docker(一):認識docker

1、docker由來

  Docker 最初是 dotCloud 公司創始人Solomon Hykes 在法國期間發起的一個公司內部項目,它是基於 dotCloud 公司多年雲服務技術的一次革新,並於 2013 年 3 月以 Apache 2.0 受權協議開源,主要項目代碼在 GitHub 上進行維護。因爲 Docker 項目的火爆,在 2013 年末,dotCloud 公司決定更名爲 Docker。Docker 最初是在 Ubuntu 12.04 上開發實現的;Red Hat則從 RHEL 6.5 開始對 Docker 進行支持;Docker 項目後來還加入了 Linux 基金會,併成立推進開放容器聯盟(OCI)。nginx

  說到docker開源就插播一段故事,docker的火爆讓一家公司甚是惆悵,沒錯就是Google,聽說Google悄悄研究容器已經十幾年了,原本準備做爲殺手鐗的,沒想到半路殺出個docker,迅速佔領容器大半江山,怎麼辦?容器領域已經木得了,那隻能換道了,容器通常是須要和編排工具配套使用的,此時Google本身的編排工具已經用了十幾年了,該踩的坑都踩的差很少了,當機立斷,k8s橫空出世,幾乎橫掃了編排工具領域的全部玩家,獨領風騷。另外雖然說docker確實火爆,可是docker公司始終沒有辦法變現,因此就在後面發行的docker中附帶了兩個licence,社區版和企業版,docker把社區版更名爲Moby,把原來開源的docker的流量所有引入到了企業版上,這樣使得docker社區直接炸鍋了,「步搖碧蓮」,「對不起社區」等等謾罵聲接踵而來,雖而後來docker的CEO出面解釋,但仍是使得那段時間使用docker的人心存疑慮。相比而言,Google就很是聰明瞭,主導成立了CNCF(Cloud Native Computing Foundation,雲原生計算基金會),將k8s的源碼直接捐給CNCF,代表立場:我不會作那種「步搖碧蓮」的事,大夥放心用,k8s的主導是CNCF組織,不是我一家的東西。這也就是後來k8s社區茁壯成長的緣由。以後,CNCF聯合google糾集除docker外的幾乎所有作容器的公司準備給docker制定標準(運行、管理、文件格式等等),不過這麼作明擺着是針對docker,有點以大欺小的意思,因此他們就給docker放話了:「小子,給你個機會,這個標準由你來定,可是你得把docker開源出來」。結果麼,就是如今的結果,你們夥一塊兒happy,其樂融融。docker

  Docker 使用 Google 公司推出的 Go 語言進行開發實現(k8s也是Go語言),基於 Linux 內核的cgroup,namespace,以及 AUFS 類的 Union FS 等技術,對進程進行封裝隔離,屬於操做系統層面的虛擬化技術。因爲隔離的進程獨立於宿主和其它的隔離的進程,所以也稱其爲容器。最初實現是基於 LXC,從 0.7 版本之後開始去除 LXC,轉而使用自行開發的 libcontainer,從 1.11 開始,則進一步演進爲使用 runC 和 containerd。ubuntu

2、什麼是docker

  docker應該是目前最流行的容器解決方案,它的思想來源於集裝箱,集裝箱的做用是什麼?封存、隔離貨物。咱們把海鮮和水果分別裝在不一樣的集裝箱裏,由同一艘大船去運輸。這是否是要比分兩艘船來的方便、快捷、高效呢。舉例:公司的開發環境和生產環境不一致,開發出來的程序在開發人員本地能運行,上了生產卻運行不了。你懂得,這個時候就要開始甩鍋了。這中狀況若是用docker就不同了,咱們直接把開發環境build成一個鏡像,而後由運維去把這個docker鏡像部署上就OK了。環境一毛同樣。安全

  docker與虛擬化的區別以下圖。傳統虛擬化是虛擬出一套硬件後,在其上運行一個完整的操做系統,在系統之上再運行應用進程;而容器內的應用進程直接運行於宿主機的內核,容器內沒有本身的內核,也沒有進行硬件虛擬。所以容器要比傳統虛擬機更爲輕便的。服務器

圖1 - 傳統虛擬化
圖2 - Docker

3、爲何要用docker?

  1. 更高效的利用系統資源
      因爲容器不須要進行硬件虛擬以及運行完整操做系統等額外開銷,Docker 對系統資源的利用率更高。不管是應用執行速度、內存損耗或者文件存儲速度,都要比傳統虛擬機技術更高效。所以,相比虛擬機技術,一個相同配置的主機,每每能夠運行更多數量的應用。網絡

  2. 更短的啓動時間
      傳統的虛擬機技術啓動應用服務每每須要數分鐘,而 Docker 容器應用是直接運行於宿主內核,無需啓動完整的操做系統,所以能夠作到秒級、甚至毫秒級的啓動時間。大大的節約了開發、測試、部署的時間。架構

  3. 一致的運行環境
      開發過程當中一個常見的問題是環境一致性問題。因爲開發環境、測試環境、生產環境不一致,致使有些 bug 並未在開發過程當中被發現。而 Docker 的鏡像提供了除內核外完整的運行時環境,確保了應用運行環境一致性,從而不會再出現 「這段代碼在我機器上沒問題啊」 這類問題。app

  4. 持續交付和部署
      對開發和運維(DevOps)人員來講,最但願的就是一次建立或配置,能夠在任意地方正常運行。使用 Docker 能夠經過定製應用鏡像來實現持續集成、持續交付、部署。開發人員能夠經過 Dockerfile 來進行鏡像構建,並結合持續集成(Continuous Integration) 系統進行集成測試,而運維人員則能夠直接在生產環境中快速部署該鏡像,甚至結合持續部署(Continuous Delivery/Deployment) 系統進行自動部署。並且使用 Dockerfile 使鏡像構建透明化,不只僅開發團隊能夠理解應用運行環境,也方便運維團隊理解應用運行所需條件,幫助更好的生產環境中部署該鏡像。運維

  5. 更輕鬆的遷移
      因爲 Docker 確保了執行環境的一致性,使得應用的遷移更加容易。Docker 能夠在不少平臺上運行,不管是物理機、虛擬機、公有云、私有云,甚至是筆記本,其運行結果是一致的。所以用戶能夠很輕易的將在一個平臺上運行的應用,遷移到另外一個平臺上,而不用擔憂運行環境的變化致使應用沒法正常運行的狀況。dom

  6. 更輕鬆的維護和擴展
      Docker 使用的分層存儲以及鏡像的技術,使得應用重複部分的複用更爲容易,也使得應用的維護更新更加簡單,基於基礎鏡像進一步擴展鏡像也變得很是簡單。此外,Docker 團隊同各個開源項目團隊一塊兒維護了一大批高質量的官方鏡像,既能夠直接在生產環境使用,又能夠做爲基礎進一步定製,大大的下降了應用服務的鏡像製做成本。

  7. 對比傳統虛擬機總結

特性 容器 虛擬機
啓動 秒級 分鐘級
硬盤使用 通常爲MB 通常爲GB
性能 接近原生 弱於
系統支持量 單機支持上千個容器 通常幾十個

4、docker組件

鏡像(image)

  操做系統分爲內核空間和用戶空間。對於 Linux 而言,內核啓動後,會掛載 root 文件系統爲其提供用戶空間支持。而 Docker 鏡像(Image),就至關因而一個 root 文件系統。好比官方鏡像ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系統的 root 文件系統。docker充分利用Union FS的技術獎docker鏡像設計成分層存儲的架構,也就是說docker鏡像並不是是由ISO那樣的打包文件,而是由一組文件系統組成。鏡像構建時也是分層構建,前一層是後一層的基礎。每一層構建完就不會再發生改變,後一層上的任何改變只發生在本身這一層。好比,刪除前一層文件的操做,實際不是真的刪除前一層的文件,而是僅在當前層標記爲該文件已刪除。在最終容器運行的時候,雖然不會看到這個文件,可是實際上該文件會一直跟隨鏡像。另外每一層都是隻讀的,只有容器啓動後,纔會在最上層生成一個可寫層。關於鏡像構建,將會在後續博客中進一步講解。

容器(container)

  容器啓動必需要依賴鏡像,它是鏡像運行時的實體。容器能夠被建立、啓動、中止、刪除、暫停等。容器的實質是進程,但與直接在宿主執行的進程不一樣,容器進程運行於屬於本身的獨立的 命名空間。所以容器能夠擁有本身的 root 文件系統、本身的網絡配置、本身的進程空間,甚至本身的用戶 ID 空間。容器內的進程是運行在一個隔離的環境裏,使用起來,就好像是在一個獨立於宿主的系統下操做同樣。這種特性使得容器封裝的應用比直接在宿主運行更加安全。也由於這種隔離的特性,不少人初學Docker 時經常會混淆容器和虛擬機。

  容器運行時,在其最上層會建立一個當前容器的可寫層,也稱爲容器存儲層。容器存儲層的生存週期和容器同樣,容器消亡時,容器存儲層也隨之消亡。所以,任何保存於容器存儲層的信息都會隨容器刪除而丟失。so,容器不該該向其存儲層內寫入任何數據,容器存儲層要保持無狀態化。全部的文件寫入操做,都應該使用數據卷(Volume)或者綁定宿主目錄,這種狀況讀寫操做就會跳過容器存儲層,直接對宿主機(或網絡存儲)發生讀寫,其性能和穩定性更高,容器刪除或者從新運行以後,數據也不會丟失。

倉庫(repository)

  鏡像構建完成後,能夠很容易的在當前宿主機上運行,可是,若是須要在其它服務器上使用這個鏡像,咱們就須要一個集中的存儲、分發鏡像的服務,Docker Registry 就是這樣的服務。一個 Docker Registry 中能夠包含多個倉庫( Repository );每一個倉庫能夠包含多個標籤( Tag );每一個標籤對應一個鏡像。一般,一個倉庫會包含同一個軟件不一樣版本的鏡像,而標籤就用於區分軟件的不一樣版本。咱們能夠經過 <倉庫名> : <標籤> 的格式來指定具體是這個軟件哪一個版本的鏡像。若是不給出標籤,將以 latest 做爲默認標籤。以nginx爲例,docker pull nginx:1.14就是指定下載nginx的1.14版本,docker pull nginx就是直接下載最新的版本。

  Docker Registry 公開服務是開放給用戶使用、容許用戶管理鏡像的 Registry 服務。通常這類公開服務容許用戶免費上傳、下載公開的鏡像,並可能提供收費服務供用戶管理私有鏡像。最常使用的 Registry 公開服務是官方的 Docker Hub,這也是默認的 Registry,並擁有大量的高質量的官方鏡像。除此之外,還有 CoreOS 的 Quay.io,CoreOS 相關的鏡像存儲在這裏;Google 的 Google Container Registry,Kubernetes 的鏡像使用的就是這個服務。因爲某些緣由,在國內訪問這些服務可能會比較慢。國內的一些雲服務商提供了針對 Docker Hub 的鏡像服務( Registry Mirror ),這些鏡像服務被稱爲加速器。常見的有阿里雲加速器、DaoCloud 加速器等。後面的docker安裝博客中會提到加速器的使用。

  除了使用公開服務外,用戶還能夠在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 鏡像,能夠直接使用作爲私有 Registry 服務。開源的 Docker Registry 鏡像只提供了 Docker Registry API 的服務端實現,足以支持 docker 命令,不影響使用。但不包含圖形界面,以及鏡像維護、用戶管理、訪問控制等高級功能。在官方的商業化版本 Docker Trusted Registry 中,提供了這
些高級功能。除了官方的 Docker Registry 外,還有第三方軟件實現了 Docker Registry API,甚至提供了用戶界面以及一些高級功能。好比,Harbor 和 Sonatype Nexus。通常企業都會選擇本身搭建 Docker Registry,相比會更加安全些。具體後面也會講。

5、docker運行流程

  以下圖所示,運行一個容器的過程:

  1. 去registry中拉取鏡像,若是本地已經存在,則直接使用本地鏡像
  2. 根據鏡像建立容器
  3. 給容器分配文件系統,並在最上層掛載一個可讀寫層。
  4. 分配網絡接口,建立一個容許容器和宿主機訪問得網絡接口
  5. 運行指定的程序
  6. 收集容器的運行狀態

6、docker底層技術

Namespaces

  1. PID Namespace:不一樣容器的進程就是經過PID Namespace隔離的,每一個容器中都會有PID爲1的進程,每一個容器中的進程都是docker daemon的子進程。

  2. Mnt Namespace:隔離文件系統掛載點。每一個容器能看到不一樣的文件系統層次結構。

  3. User Namespace:隔離用戶ID和組ID。每一個容器都有本身的 user 和 group ID,能夠跟宿主機的不一樣,宿主機中的非特權用戶能夠成爲容器內的特權用戶。

  4. Net Namespace:每一個容器用有其獨立的網絡設備,IP 地址,IP 路由表,/proc/net 目錄等等。docker默認採用 veth 的方式將容器中的虛擬網卡同host上的一個docker bridge: docker0鏈接在一塊兒。

  5. UTS Namespace:UTS Namespace容許每一個容器擁有獨立的hostname和domain name,使其在網絡上能夠被視做一個獨立的節點而非宿主機上的一個進程。

  6. IPC Nampspace:每一個容器有其本身的 System V IPC 和 POSIX 消息隊列,所以,只有在同一個 IPC namespace 的進程之間才能互相通訊。

Control groups

  把系統級的資源分紅多個組,而後把組內的資源分配到用戶空間的進程上去。cgroups能夠限制如下九大資源:

  • blkio:設置限制每一個塊設備的輸入輸出控制。例如:磁盤,光盤以及usb等等。
  • cpu:使用調度程序爲cgroup任務提供cpu的訪問。
  • cpuacct:產生cgroup任務的cpu資源報告。
  • cpuset:CPU核心的分派 。CPU有兩種分配方式,按比例和按核數。
  • devices:容許或拒絕cgroup任務對設備的訪問。
  • freezer:暫停和恢復cgroup任務。
  • memory:設置每一個cgroup的內存限制以及產生內存資源報告。
  • perf_event:對cgroup中的任務進行統一性能測試。
  • net_cls:標記每一個網絡包以供cgroup方便使用。

Union file systems

  Docker Engine 使用Union FS爲容器提供構建模塊(使用此技術實現聯合掛載),Docker Engine 可使用多種不一樣的Union FS技術,包括AUFS、btrfs、vfs和DeviceMapper。鏡像從registry中拉下以後會存儲在本地一個專門存儲鏡像的空間中,這個存儲空間須要是特殊並且專用的文件系統,Ubuntu系統下默認使用的是AUFS (advanced multi-layered unification filesystem) ;而在Centos7上新版docker使用的是overlayFS(自從OverlayFS加入kernel主線後,它在kernel模塊中的名稱就被從overlayfs改成overlay了。可是爲了在本文中區別,咱們仍使用OverlayFS表明整個文件系統)。overlayFS是一種二層抽象的文件系統,早期的overlay和如今的overlay2就是overlayFS的存儲驅動,它須要建構在宿主機的文件系統之上,以下:

[root@docker1 ~]# cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core) 
[root@docker1 ~]# uname -r
3.10.0-693.el7.x86_64
[root@docker1 ~]# docker info
Server Version: 18.09.6
Storage Driver: overlay2
 Backing Filesystem: xfs


參考資料

  • docker從入門到實戰:docker practice
  • docker官方文檔:https://docs.docker.com/


寫做不易,轉載請註明出處,謝謝~~

相關文章
相關標籤/搜索