【深度知識】DOCKER入門,框架原理,鏡像製作和資源列表

1. 摘要

本文是輝哥Docker入門的一些摘要和資源分享,涉及DOCKER入門,框架原理,鏡像製作和資源列表等內容。作爲自己學習的備忘,也分享給有需要的同學了。

2. 內容

2.1 Docker的定義和優勢

Docker 屬於 Linux 容器的一種封裝,提供簡單易用的容器使用接口。它是目前最流行的 Linux 容器解決方案。

Docker 將應用程序與該程序的依賴,打包在一個文件裏面。運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器裏運行,就好像在真實的物理機上運行一樣。有了 Docker,就不用擔心環境問題。

總體來說,Docker 的接口相當簡單,用戶可以方便地創建和使用容器,把自己的應用放入容器。容器還可以進行版本管理、複製、分享、修改,就像管理普通的代碼一樣。

下面的圖片比較了 Docker 和傳統虛擬化方式的不同之處。傳統虛擬機技術是虛擬出一套硬件後,在其上運行一個完整操作系統,在該系統上再運行所需應用進程;而容器內的應用進程直接運行於宿主的內核,容器內沒有自己的內核,而且也沒有進行硬件虛擬。因此容器要比傳統虛擬機更爲輕便。

Docker 的優勢

Docker 相比於傳統虛擬化方式具有更多的優勢:

  • Docker 啓動快速屬於秒級別。
    虛擬機通常需要幾分鐘去啓動。
  • Docker 需要的資源更少。
    Docker 在操作系統級別進行虛擬化,Docker 容器和內核交互,幾乎沒有性能損耗,性能優於通過 Hypervisor 層與內核層的虛擬化。
  • Docker 更輕量。
    Docker 的架構可以共用一個內核與共享應用程序庫,所佔內存極小。同樣的硬件環境,Docker 運行的鏡像數遠多於虛擬機數量,對系統的利用率非常高。
  • 與虛擬機相比,Docker 隔離性更弱。
    Docker 屬於進程之間的隔離,虛擬機可實現系統級別隔離。
  • 安全性。
    Docker 的安全性也更弱,Docker 的租戶 Root 和宿主機 Root 等同,一旦容器內的用戶從普通用戶權限提升爲 Root 權限,它就直接具備了宿主機的 Root 權限,進而可進行無限制的操作。
    虛擬機租戶 Root 權限和宿主機的 Root 虛擬機權限是分離的,並且虛擬機利用如 Intel 的 VT-d 和 VT-x 的 ring-1 硬件隔離技術。
    這種隔離技術可以防止虛擬機突破和彼此交互,而容器至今還沒有任何形式的硬件隔離,這使得容器容易受到攻擊。
  • 可管理性。
    Docker 的集中化管理工具還不算成熟。各種虛擬化技術都有成熟的管理工具,例如 VMware vCenter 提供完備的虛擬機管理能力。
  • 高可用和可恢復性。
    Docker 對業務的高可用支持是通過快速重新部署實現的。
    虛擬化具備負載均衡,高可用,容錯,遷移和數據保護等經過生產實踐檢驗的成熟保障機制, VMware 可承諾虛擬機 99.999% 高可用,保證業務連續性。
  • 快速創建、刪除。
    虛擬化創建是分鐘級別的,Docker 容器創建是秒級別的,Docker 的快速迭代性,決定了無論是開發、測試、部署都可以節約大量時間
  • 交付、部署。
    虛擬機可以通過鏡像實現環境交付的一致性,但鏡像分發無法體系化。Docker 在 Dockerfile 中記錄了容器構建過程,可在集羣中實現快速分發和快速部署。

DOCKER vs 傳統虛擬機總結:

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

2.2 Docker 入門教程

入門一個技術的最好方法就是把手弄溼,做一個最簡的實踐。
阮一峯的《Docker 入門教程》Docker 微服務教程教學文檔通俗易懂,跟着實操一把吧。

2.3 Docker的基本概念(Image/Container/Repository)

從上圖我們可以看到,Docker 中包括三個基本的概念:
Image(鏡像)
Container(容器)
Repository(倉庫)

鏡像是 Docker 運行容器的前提,倉庫是存放鏡像的場所,可見鏡像更是 Docker 的核心。

Image(鏡像)

那麼鏡像到底是什麼呢?Docker 鏡像可以看作是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。

鏡像不包含任何動態數據,其內容在構建之後也不會被改變。鏡像(Image)就是一堆只讀層(read-only layer)的統一視角,也許這個定義有些難以理解,下面的這張圖能夠幫助讀者理解鏡像的定義:

從左邊我們看到了多個只讀層,它們重疊在一起。除了最下面一層,其他層都會有一個指針指向下一層。這些層是 Docker 內部的實現細節,並且能夠在主機的文件系統上訪問到。

統一文件系統(Union File System)技術能夠將不同的層整合成一個文件系統,爲這些層提供了一個統一的視角。

這樣就隱藏了多層的存在,在用戶的角度看來,只存在一個文件系統。我們可以在圖片的右邊看到這個視角的形式。

Container(容器)

容器(Container)的定義和鏡像(Image)幾乎一模一樣,也是一堆層的統一視角,唯一區別在於容器的最上面那一層是可讀可寫的。

由於容器的定義並沒有提及是否要運行容器,所以實際上,容器 = 鏡像 + 讀寫層。

Repository(倉庫)

Docker 倉庫是集中存放鏡像文件的場所。鏡像構建完成後,可以很容易的在當前宿主上運行。

但是, 如果需要在其他服務器上使用這個鏡像,我們就需要一個集中的存儲、分發鏡像的服務,Docker Registry(倉庫註冊服務器)就是這樣的服務。

有時候會把倉庫(Repository)和倉庫註冊服務器(Registry)混爲一談,並不嚴格區分。

Docker 倉庫的概念跟 Git 類似,註冊服務器可以理解爲 GitHub 這樣的託管服務。

實際上,一個 Docker Registry 中可以包含多個倉庫(Repository),每個倉庫可以包含多個標籤(Tag),每個標籤對應着一個鏡像。

所以說,鏡像倉庫是 Docker 用來集中存放鏡像文件的地方,類似於我們之前常用的代碼倉庫。

通常,一個倉庫會包含同一個軟件不同版本的鏡像,而標籤就常用於對應該軟件的各個版本 。

我們可以通過<倉庫名>:<標籤>的格式來指定具體是這個軟件哪個版本的鏡像。如果不給出標籤,將以 Latest 作爲默認標籤。

倉庫又可以分爲兩種形式:

  • Public(公有倉庫)
  • Private(私有倉庫)

Docker Registry 公有倉庫是開放給用戶使用、允許用戶管理鏡像的 Registry 服務。

一般這類公開服務允許用戶免費上傳、下載公開的鏡像,並可能提供收費服務供用戶管理私有鏡像。

除了使用公開服務外,用戶還可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 鏡像,可以直接使用做爲私有 Registry 服務。

當用戶創建了自己的鏡像之後就可以使用 Push 命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個鏡像時候,只需要從倉庫上 Pull 下來就可以了。

2.4 Docker的架構和原理

Docker 使用的是 C/S 結構,即客戶端/服務器體系結構, Docker 客戶端和服務端可以運行在一臺機器上,我們可以通過 RESTful 、Stock 或網絡接口與遠程 Docker 服務端進行通信。

Docker 的核心組件包括:
Docker Client
Docker Daemon
Docker Image
Docker Registry
Docker Container

Docker 採用的是 Client/Server 架構。客戶端向服務器發送請求,服務器負責構建、運行和分發容器。

客戶端和服務器可以運行在同一個 Host 上,客戶端也可以通過 Socket 或 REST API 與遠程的服務器通信。

Docker Client

Docker Client ,也稱 Docker 客戶端。它其實就是 Docker 提供命令行界面(CLI)工具,是許多 Docker 用戶與 Docker 進行交互的主要方式。

客戶端可以構建,運行和停止應用程序,還可以遠程與 Docker_Host 進行交互。

最常用的 Docker 客戶端就是 Docker 命令,我們可以通過 Docker 命令很方便地在 Host 上構建和運行 Docker 容器。

Docker Daemon

Docker Daemon 是服務器組件,以 Linux 後臺服務的方式運行,是 Docker 最核心的後臺進程,我們也把它稱爲守護進程。

它負責響應來自 Docker Client 的請求,然後將這些請求翻譯成系統調用完成容器管理操作。

該進程會在後臺啓動一個 API Server ,負責接收由 Docker Client 發送的請求,接收到的請求將通過 Docker Daemon 內部的一個路由分發調度,由具體的函數來執行請求。

我們大致可以將其分爲以下三部分:

  • Docker Server
  • Engine
  • Job

Docker Daemon 的架構如下所示:

Docker Daemon 可以認爲是通過 Docker Server 模塊接受 Docker Client 的請求,並在 Engine 中處理請求,然後根據請求類型,創建出指定的 Job 並運行。

Docker Daemon 運行在 Docker Host 上,負責創建、運行、監控容器,構建、存儲鏡像。

運行過程的作用有以下幾種可能:

  • 向 Docker Registry 獲取鏡像。
  • 通過 GraphDriver 執行容器鏡像的本地化操作。
  • 通過 NetworkDriver 執行容器網絡環境的配置。
  • 通過 ExecDriver 執行容器內部運行的執行工作。

由於 Docker Daemon 和 Docker Client 的啓動都是通過可執行文件 Docker 來完成的,因此兩者的啓動流程非常相似。

Docker 可執行文件運行時,運行代碼通過不同的命令行 Flag 參數,區分兩者,並最終運行兩者各自相應的部分。

啓動 Docker Daemon 時,一般可以使用以下命令來完成:

docker --daemon = truedocker –d
docker –d = true

再由 Docker 的 main() 函數來解析以上命令的相應 Flag 參數,並最終完成 Docker Daemon 的啓動。

下圖可以很直觀地看到 Docker Daemon 的啓動流程:

默認配置下,Docker Daemon 只能響應來自本地 Host 的客戶端請求。如果要允許遠程客戶端請求,需要在配置文件中打開 TCP 監聽。

我們可以照着如下步驟進行配置:

1、編輯配置文件/etc/systemd/system/multi-user.target.wants/docker.service,在環境變量 ExecStart 後面添加 -H tcp://0.0.0.0,允許來自任意 IP 的客戶端連接。

2、重啓 Docker Daemon:

systemctl daemon-reload
systemctl restart docker.service

3、我們通過以下命令即可實現與遠程服務器通信:

docker -H 服務器IP地址 info

-H 是用來指定服務器主機,info 子命令用於查看 Docker 服務器的信息。

Docker Image

Docker 鏡像可以看作是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。

鏡像不包含任何動態數據,其內容在構建之後也不會被改變。我們可將 Docker 鏡像看成只讀模板,通過它可以創建 Docker 容器。

鏡像有多種生成方法:

  • 從無到有開始創建鏡像
  • 下載並使用別人創建好的現成的鏡像
  • 在現有鏡像上創建新的鏡像

我們可以將鏡像的內容和創建步驟描述在一個文本文件中,這個文件被稱作 Dockerfile ,通過執行 docker build 命令可以構建出 Docker 鏡像。

Docker Registry

Docker Registry 是存儲 Docker Image 的倉庫,它在 Docker 生態環境中的位置如下圖所示:

運行 docker push、docker pull、docker search 時,實際上是通過 Docker Daemon 與 Docker Registry 通信。

Docker Container

Docker 容器就是 Docker 鏡像的運行實例,是真正運行項目程序、消耗系統資源、提供服務的地方。

Docker Container 提供了系統硬件環境,我們可以使用 Docker Images 這些製作好的系統盤,再加上我們所編寫好的項目代碼,Run 一下就可以提供服務啦。

Docker 組件是如何協作運行容器

看到這裏,我相信各位讀者朋友們應該已經對 Docker 基礎架構熟悉的差不多了,我們還記得運行的第一個容器嗎?

現在我們再通過 hello-world 這個例子來體會一下 Docker 各個組件是如何協作的。

容器啓動過程如下:
Docker 客戶端執行 docker run 命令。
Docker Daemon 發現本地沒有 hello-world 鏡像。
Daemon 從 Docker Hub 下載鏡像。
下載完成,鏡像 hello-world 被保存到本地。
Docker Daemon 啓動容器。

具體過程可以看如下這幅演示圖:

我們可以通過 Docker Images 可以查看到 hello-world 已經下載到本地:

我們可以通過 Docker Ps 或者 Docker Container ls 顯示正在運行的容器,我們可以看到,hello-world 在輸出提示信息以後就會停止運行,容器自動終止,所以我們在查看的時候沒有發現有容器在運行。

我們把 Docker 容器的工作流程剖析的十分清楚了,我們大體可以知道 Docker 組件協作運行容器可以分爲以下幾個過程:
Docker 客戶端執行 docker run 命令。
Docker Daemon 發現本地沒有我們需要的鏡像。
Daemon 從 Docker Hub 下載鏡像。
下載完成後,鏡像被保存到本地。
Docker Daemon 啓動容器。

2.5 Docker常用命令

我們可以通過 docker -h 去查看命令的詳細的幫助文檔。在這裏我只會講一些日常我們可能會用的比較多的一些命令。

具體的命令詳解參考《【知識分享】Docker 命令大全》

2.6 Dockerfile和Image鏡像製作

鏡像的定製實際上就是定製每一層所添加的配置、文件。如果我們可以把每一層修改、安裝、構建、操作的命令都寫入一個腳本,用這個腳本來構建、定製鏡像,那麼之前提及的無法重複的問題、鏡像構建透明性的問題、體積的問題就都會解決。這個腳本就是 Dockerfile。

Dockerfile 是一個文本文件,其內包含了一條條的 指令(Instruction),每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。

我們可以通過下面這幅圖來直觀地感受下 Docker 鏡像、容器和 Dockerfile 三者之間的關係:

我們從上圖中可以看到,Dockerfile 可以自定義鏡像,通過 Docker 命令去運行鏡像,從而達到啓動容器的目的。Dockerfile 是由一行行命令語句組成,並且支持已 # 開頭的註釋行。

一般來說,我們可以將 Dockerfile 分爲四個部分:

  • 基礎鏡像(父鏡像)信息指令 FROM。
  • 維護者信息指令 MAINTAINER。
  • 鏡像操作指令 RUN 、EVN 、ADD 和 WORKDIR 等。
  • 容器啓動指令 CMD 、ENTRYPOINT 和 USER 等。

以定製 nginx 鏡像爲例,這次我們使用 Dockerfile 來定製。

在一個空白目錄中,建立一個文本文件,並命名爲 Dockerfile:

$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile

其內容爲:

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

這個 Dockerfile 很簡單,一共就兩行。涉及到了兩條指令,FROM 和 RUN。

Dockerfile 常用的指令

更多的指令解釋參考《Dockerfile 指令詳解》, 裏面包含以下指令說明:

3.參考

(1)Docker 入門教程-阮一峯
http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html
【點評】簡單,易懂,包含實踐操作,體驗好。

(2)Docker 微服務教程-阮一峯
http://www.ruanyifeng.com/blog/2018/02/docker-wordpress-tutorial.html
【點評】一個docker微服務wordpress案例,使用docker,Docker Compose實踐。

(2)Docker — 從入門到實踐
https://yeasy.gitbooks.io/docker_practice/
【點評】全面,質量高,關於Dockerfile的講的不錯。還涉及Kubernetes,Docker Compose的介紹。

(3)這可能是最爲詳細的Docker入門總結
https://juejin.im/entry/5beacface51d4507a717765f
【點評】有很多框架圖,適合瞭解原理。

(4)Docker從入門到實踐-W3CSchool
https://www.w3cschool.cn/reqsgr/

(5)Docker 教程 | 菜鳥教程
https://www.runoob.com/docker/docker-tutorial.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章