【Docker系列教程之三】Docker容器是如何工作的
在上一篇的文章中,我給大家主要介紹了一下 Docker
環境的搭建,簡單的講解了一下 Docker
架構,以及用 Docker
命令簡單演示了一下如何拉去一個 images
映象。本篇我們將剖析一下 Docker
容器是如何工作的,學習好Docker容器工作的原理,我們就可以自己去管理我們的容器了。
Docker架構
在上一篇文章的學習中,我們簡單地講解了Docker的基本架構。瞭解到了 Docker
使用的是 C/S
結構,即客戶端/伺服器體系結構。明白了 Docker
客戶端與 Docker
伺服器進行互動時, Docker
服務端負責構建、執行和分發 Docker
映象。 也知道了 Docker
客戶端和服務端可以執行在一臺機器上,可以通過 RESTful
、 stock
或網路介面與遠端 Docker
服務端進行通訊。
我們從下圖可以很直觀的瞭解到Docker的架構:
Docker
的核心元件包括:
-
Docker Client
-
Docker daemon
-
Docker Image
-
Docker Registry
-
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、我們通過以下命令即可實現與遠端伺服器通訊
-
docker -H 伺服器IP地址 info
-H
是用來指定伺服器主機, info
子命令用於檢視 Docker
伺服器的資訊
Docker Image
在開篇那文【Docker系列教程之一】Docker入門中我已經提到過, Docker
映象可以看作是一個特殊的檔案系統,除了提供容器執行時所需的程式、庫、資源、配置等檔案外,還包含了一些為執行時準備的一些配置引數(如匿名卷、環境變數、使用者等)。映象不包含任何動態資料,其內容在構建之後也不會被改變。我們可將 Docker
映象看成只讀模板,通過它可以建立 Docker
容器。
映象有多種生成方法:
-
從無到有開始建立映象
-
下載並使用別人建立好的現成的映象
-
在現有映象上建立新的映象
我們可以將映象的內容和建立步驟描述在一個文字檔案中,這個檔案被稱作 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
的一些基本概念、如何構建一個映象等相關內容。