1. 程式人生 > >【Docker系列教程之三】Docker容器是如何工作的

【Docker系列教程之三】Docker容器是如何工作的

在上一篇的文章中,我給大家主要介紹了一下 Docker 環境的搭建,簡單的講解了一下 Docker 架構,以及用 Docker 命令簡單演示了一下如何拉去一個 images 映象。本篇我們將剖析一下 Docker 容器是如何工作的,學習好Docker容器工作的原理,我們就可以自己去管理我們的容器了。

Docker架構

在上一篇文章的學習中,我們簡單地講解了Docker的基本架構。瞭解到了 Docker 使用的是 C/S 結構,即客戶端/伺服器體系結構。明白了 Docker

 客戶端與 Docker 伺服器進行互動時, Docker 服務端負責構建、執行和分發 Docker 映象。 也知道了 Docker 客戶端和服務端可以執行在一臺機器上,可以通過 RESTful 、 stock 或網路介面與遠端 Docker 服務端進行通訊。

我們從下圖可以很直觀的瞭解到Docker的架構:

Docker 的核心元件包括:

  1. Docker Client

  2. Docker daemon

  3. Docker Image

  4. Docker Registry

  5. Docker Container

Docker 採用的是 Client/Server 架構。客戶端向伺服器傳送請求,伺服器負責構建、執行和分發容器。客戶端和伺服器可以執行在同一個 Host 上,客戶端也可以通過 socket 或 REST API 與遠端的伺服器通訊。可能很多朋友暫時不太理解一些東西,比如 REST API 是什麼東西等,不過沒關係,在後面的教程中會一一給大家講解清楚。

Docker Client

DockerClient

 ,也稱 Docker 客戶端。它其實就是 Docker 提供命令列介面 (CLI) 工具,是許多 Docker 使用者與 Docker 進行互動的主要方式。客戶端可以構建,執行和停止應用程式,還可以遠端與 Docker_Host進行互動。最常用的 Docker 客戶端就是 docker 命令,我們可以通過 docker 命令很方便地在 host 上構建和執行 docker 容器。

Docker daemon

Dockerdaemon 是伺服器元件,以 Linux 後臺服務的方式執行,是 Docker 最核心的後臺程序,我們也把它稱為守護程序。它負責響應來自 DockerClient 的請求,然後將這些請求翻譯成系統呼叫完成容器管理操作。該程序會在後臺啟動一個 APIServer ,負責接收由 DockerClient 傳送的請求,接收到的請求將通過 Dockerdaemon內部的一個路由分發排程,由具體的函式來執行請求。

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

  • Docker Server

  • Engine

  • Job

Docker Daemon的架構如下所示:

DockerDaemon 可以認為是通過 DockerServer 模組接受 DockerClient 的請求,並在 Engine 中處理請求,然後根據請求型別,創建出指定的 Job 並執行。 DockerDaemon 執行在 Dockerhost 上,負責建立、執行、監控容器,構建、儲存映象。

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

  • 向 DockerRegistry 獲取映象

  • 通過 graphdriver 執行容器映象的本地化操作

  • 通過 networkdriver 執行容器網路環境的配置

  • 通過 execdriver 執行容器內部執行的執行工作

由於 DockerDaemon 和 DockerClient 的啟動都是通過可執行檔案 docker 來完成的,因此兩者的啟動流程非常相似。 Docker 可執行檔案執行時,執行程式碼通過不同的命令列 flag 引數,區分兩者,並最終執行兩者各自相應的部分。

啟動 DockerDaemon 時,一般可以使用以下命令來完成

docker --daemon = true

docker –d

docker –d = true

 

再由 docker 的 main() 函式來解析以上命令的相應 flag 引數,並最終完成 DockerDaemon 的啟動。

下圖可以很直觀地看到 DockerDaemon 的啟動流程:

預設配置下, Dockerdaemon 只能響應來自本地 Host 的客戶端請求。如果要允許遠端客戶端請求,需要在配置檔案中開啟 TCP 監聽。我們可以照著如下步驟進行配置:

1、編輯配置檔案 /etc/systemd/system/multi-user.target.wants/docker.service ,在環境變數 ExecStart 後面新增 -H tcp://0.0.0.0,允許來自任意 IP 的客戶端連線。

2、重啟 Dockerdaemon

systemctl daemon-reload

systemctl restart docker.service

 

3、我們通過以下命令即可實現與遠端伺服器通訊

  1. docker -H 伺服器IP地址 info

-H 是用來指定伺服器主機, info 子命令用於檢視 Docker 伺服器的資訊

Docker Image

在開篇那文【Docker系列教程之一】Docker入門中我已經提到過, Docker 映象可以看作是一個特殊的檔案系統,除了提供容器執行時所需的程式、庫、資源、配置等檔案外,還包含了一些為執行時準備的一些配置引數(如匿名卷、環境變數、使用者等)。映象不包含任何動態資料,其內容在構建之後也不會被改變。我們可將 Docker 映象看成只讀模板,通過它可以建立 Docker 容器。

映象有多種生成方法:

  1. 從無到有開始建立映象

  2. 下載並使用別人建立好的現成的映象

  3. 在現有映象上建立新的映象

我們可以將映象的內容和建立步驟描述在一個文字檔案中,這個檔案被稱作 Dockerfile ,通過執行 docker build<docker-file> 命令可以構建出 Docker 映象,在後續的教程中,我們會用一篇專門討論這個問題。

Docker Registry

Dockerregistry 是儲存 docker image 的倉庫,它在 docker 生態環境中的位置如下圖所示:

執行 docker push、 docker pull、 docker search時,實際上是通過 docker daemon 與 docker registry 通訊。具體內容可以參看開篇那文【Docker系列教程之一】Docker入門

Docker Container

Docker 容器就是 Docker 映象的執行例項,是真正執行專案程式、消耗系統資源、提供服務的地方。 DockerContainer 提供了系統硬體環境,我們可以使用 DockerImages 這些製作好的系統盤,再加上我們所編寫好的專案程式碼, run 一下就可以提供服務啦。

Docker元件是如何協作執行容器

看到這裡,我相信各位讀者朋友們應該已經對Docker基礎架構已經熟悉的差不多了,我們還記得上一篇我們執行的第一個容器嗎?現在我們再通過hello-world這個例子來體會一下 Docker 各個元件是如何協作的。

容器啟動過程如下:

  • Docker 客戶端執行 docker run 命令

  • Dockerdaemon 發現本地沒有 hello-world 映象

  • daemon 從 DockerHub 下載映象

  • 下載完成,映象 hello-world 被儲存到本地

  • Dockerdaemon 啟動容器

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

我們可以通過 docker images 可以檢視到 hello-world 已經下載到本地

我們可以通過 docker ps 或者 docker container ls 顯示正在執行的容器,我們可以看到, hello-world 在輸出提示資訊以後就會停止執行,容器自動終止,所以我們在檢視的時候沒有發現有容器在執行。

總結

通過本篇文章的講解,我相信大家對 Docker 容器的工作流程已經非常清楚了,在後續的文章中,我會帶大家瞭解 Dockerfile 的一些基本概念、如何構建一個映象等相關內容。