Docker的基本原理小结

Posted EbowTang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker的基本原理小结相关的知识,希望对你有一定的参考价值。

维护人员:ebowtang
创建时间:2021-10-06
更新时间:2021-10-16
原件获取:「Docker」https://www.aliyundrive.com/s/dRNgTzvgYg5

一 Docker原理与架构
         1 Docker架构
                  1.1 Docker Client【发起请求】
                  1.2 Docker Daemon【处理请求】
                  1.3 Docker Registry【镜像仓库】
                  1.4 Graph【镜像存储】
                  1.5 Driver【真正的执行者】
                          1.51 graphdriver【镜像的管理和存储】
                          1.52 networkdriver【执行网络配置】
                          1.53 execdriver【运行配置】
                  1.6 libcontainer【操纵和配置容器】
                  1.7 Docker container【容器,交付对象】
                  1.8 Docker架构小结:
         3 Docker运行案例分析
                  3.1 docker pull(下载镜像)
                  3.2 docker run(运行容器)

一 Docker原理与架构

1 Docker架构

详细的架构图:

1.1 Docker Client【发起请求】

用户使用的可执行文件为docker,通过docker命令行工具可以发起众多管理container的请求。Docker Client可以通过以下三种方式和Docker Daemon建立通信:

tcp://host:port,
unix://path_to_socket
fd://socketfd。

为了简单起见,本文一律使用第一种方式作为讲述两者通信的原型。与此同时,与Docker Daemon建立连接并传输请求的时候,Docker Client可以通过设置命令行flag参数的形式设置安全传输层协议(TLS)的有关参数,保证传输的安全性。

Docker Client发送容器管理请求后,由Docker Daemon接受并处理请求,当Docker Client接收到返回的请求相应并简单处理后,Docker Client一次完整的生命周期就结束了。当需要继续发送容器管理请求时,用户必须再次通过docker可执行文件创建Docker Client。

1.2 Docker Daemon【处理请求】

Docker Daemon是Docker架构中一个常驻在后台的系统【守护】进程,功能是:接受并处理Docker Client发送的请求。

Docker Daemon的架构,大致可以分为以下三部分:Docker Server、Engine和Job。

Daemon组件的架构图如下。

其中:
1,Server【分发任务】是专门服务于Docker Client,接受并调度分发Docker Client发送的请求

2,Engine【运行引擎】是Docker架构中的运行引擎,同时Docker运行的核心模块。它扮演Docker container存储仓库的角色,并且通过执行job的方式来操纵管理这些容器。

3,Job【执行单元】可以认为是Docker架构中Engine内部最基本的工作执行单元。Docker可以做的每一项工作,都可以抽象为一个job。例如:在容器内部运行一个进程,这是一个job;创建一个新的容器,这是一个job,从Internet上下载一个文档,这是一个job;包括之前在Docker Server部分说过的,创建Server服务于HTTP的API,这也是一个job,等等。

1.3 Docker Registry【镜像仓库】

Docker Registry是一个存储容器镜像的仓库。而容器镜像是在容器被创建时,被加载用来初始化容器的文件架构与目录。在Docker的运行过程中,Docker Daemon会与Docker Registry通信,并实现搜索镜像、下载镜像、上传镜像三个功能,这三个功能对应的job名称分别为”search”,”pull” 与 “push”。其中,在Docker架构中,Docker可以使用公有的Docker Registry,即大家熟知的Docker Hub,如此一来,Docker获取容器镜像文件时,必须通过互联网访问

Docker Hub;同时Docker也允许用户构建本地私有的Docker Registry,这样可以保证容器镜像的获取在内网完成。

1.4 Graph【镜像存储】

Graph在Docker架构中扮演已下载容器镜像的保管者,以及已下载容器镜像之间关系的记录者。一方面,Graph存储着本地具有版本信息的文件系统镜像,另一方面也通过GraphDB记录着所有文件系统镜像彼此之间的关系。

1.5 Driver【真正的执行者】

Driver是Docker架构中的驱动模块。通过Driver驱动,Docker可以实现对Docker容器执行环境的定制。由于Docker运行的生命周期中,并非用户所有的操作都是针对Docker容器的管理,另外还有关于Docker运行信息的获取,Graph的存储与记录等。因此,为了将Docker容器的管理从Docker Daemon内部业务逻辑中区分开来,设计了Driver层驱动来接管所有这部分请求。在Docker Driver的实现中,可以分为以下三类驱动:graphdriver、networkdriver和execdriver。

1.51 graphdriver【镜像的管理和存储】

graphdriver主要用于完成容器镜像的管理,包括存储与获取。

  1. 存储:docker pull下载的镜像由graphdriver存储到本地的指定目录(Graph中)。
  2. 获取:docker run(create)用镜像来创建容器的时候由graphdriver到本地Graph中获取镜像。

1.52 networkdriver【执行网络配置】

networkdriver的用途是完成Docker容器网络环境的配置,其中包括

  1. Docker启动时为Docker环境创建网桥;
  2. Docker容器创建时为其创建专属虚拟网卡设备;
  3. Docker容器分配IP、端口并与宿主机做端口映射,设置容器防火墙策略等。

1.53 execdriver【运行配置】

  1. execdriver作为Docker容器的执行驱动,负责创建容器运行命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等。
  2. 现在execdriver默认使用native驱动,不依赖于LXC。

1.6 libcontainer【操纵和配置容器】

libcontainer是Docker架构中一个使用Go语言设计实现的函数库,设计初衷是希望该库可以不依靠任何依赖,直接访问内核中与容器相关的API。正是由于

libcontainer的存在,Docker可以直接调用libcontainer,而最终操纵容器的namespace、cgroups、apparmor、网络设备以及防火墙规则等。这一系列

操作的完成都不需要依赖LXC或者其他包。

1.7 Docker container【容器,交付对象】

Docker container(Docker容器)是Docker架构中服务交付的最终体现形式,他是镜像的一个实例,可以通过镜像克隆出多个实例容器。

Docker按照用户的需求与指令,订制相应的Docker容器:

\\* 用户通过指定容器镜像,使得Docker容器可以自定义rootfs等文件系统;
\\* 用户通过指定计算资源的配额,使得Docker容器使用指定的计算资源;
\\* 用户通过配置网络及其安全策略,使得Docker容器拥有独立且安全的网络环境;
\\* 用户通过指定运行的命令,使得Docker容器执行指定的工作。

Docker容器示意图如图

1.8 Docker架构小结:

Docker是CS架构,是一种轻量级的虚拟化,进程级别的虚拟化,简化来看主要有五个部分组成:

docker daemon(守护进程):接收以及分发任务

docker client(客户端):发起任务请求

registry(远端仓库):云端仓库,存放各种大佬的镜像,镜像的获取方式之一

containers(容器):镜像的实例化对象,实际上就是将运行环境和应用打包在一起

Images(镜像):其中镜像就是容器的模板(只读文件),是一个可执行的软件包,包含了代码,库,环境变量,和配置文件,软件内容。

docker根本的目的和任务在于创建,运行和管理容器,容器提供具体的功能。

官网描绘的简易架构图:

运行容器看看:

docker客户端发起请求,daemon守护进程负责接收请求进行任务分发,如果本地没有该镜像则到云端仓库下载,保存到本地,容器则是镜像的一个可运行实例。

在docker环境中下载hello-world测试:

[root@localhost ~]# docker run hello-world         #运行hello-world镜像
Unable to find image 'hello-world:latest' locally  #本地找不到
latest: Pulling from library/hello-world           #从云端镜像仓库下载
2db29710123e: Pull complete
Digest: sha256:cc15c5b292d8525effc0f89cb299f1804f3a725c8d05e158653a563f15e4f685
Status: Downloaded newer image for hello-world:latest

Hello from Docker!                                 #测试成功,表明工作流程正常
This message shows that your installation appears to be working correctly.
#以下是一些重要的学习信息:
To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with: #稍微复杂的容器案例
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/        #公有的Docker Registry,即大家熟知的Docker Hub

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

上面的信息中写道:

为了生成此消息,Docker采取了以下步骤:

1.Docker客户端向Docker守护程序发起请求。

2.Docker守护进程从Docker云端镜像仓库下载了“hello world”镜像(amd64)。

3.Docker守护进程根据镜像创建了一个可执行容器,其运行后生成当前输出的文字。

4.Docker守护进程将该输出流式传输到Docker客户端,客户端将其发送到你的终端上显示。

3 Docker运行案例分析

3.1 docker pull(下载镜像)

docker pull命令的作用为:Docker Registry中下载指定的容器镜像,并存储在本地的Graph中,以备后续创建Docker容器时的使

用。docker pull命令执行流程如图

如图,图中标记的红色箭头表示docker pull命令在发起后,Docker所做的一系列运行。以下逐一分析这些步骤。

(1) Docker Client接受docker pull命令,解析完请求以及收集完请求参数之后,发送一个HTTP请求给Docker Server,HTTP请求方法为

POST,请求URL为”/images/create? “+”xxx”;

(2) Docker Server接受以上HTTP请求,并交给mux.Router,mux.Router通过URL以及请求方法来确定执行该请求的具体handler;

(3) mux.Router将请求路由分发至相应的handler,具体为PostImagesCreate;

(4) 在PostImageCreate这个handler之中,一个名为”pull”的job被创建,并开始执行;

(5) 名为”pull”的job在执行过程中,执行pullRepository操作,即从Docker Registry中下载相应的一个或者多个image;

(6) 名为”pull”的job将下载的image交给graphdriver;

(7) graphdriver负责将image进行存储,一方创建graph对象,另一方面在GraphDB中记录image之间的关系。

3.2 docker run(运行容器)

docker run命令的作用是在一个全新的Docker容器内部运行一条指令。Docker在执行这条命令的时候,所做工作可以分为两部分:

第一,创建Docker容器所需的rootfs;

第二,创建容器的网络等运行环境,并真正运行用户指令。

因此,在整个执行流程中,Docker Client给Docker Server发送了两次HTTP请求,第二次请求的发起取决于第一次请求的返回状态。

Docker run命令执行流程如图。

(1) Docker Client接受docker run命令,解析完请求以及收集完请求参数之后,发送一个HTTP请求给Docker Server,HTTP请求方法为

POST,请求URL为”/containers/create? “+”xxx”;

(2) Docker Server接受以上HTTP请求,并交给mux.Router,mux.Router通过URL以及请求方法来确定执行该请求的具体handler;

(3) mux.Router将请求路由分发至相应的handler,具体为PostContainersCreate;

(4) 在PostImageCreate这个handler之中,一个名为”create”的job被创建,并开始让该job运行;

(5) 名为”create”的job在运行过程中,执行Container.Create操作,该操作需要获取容器镜像来为Docker容器创建rootfs,即调用graphdriver;

(6) graphdriver从Graph中获取创建Docker容器rootfs所需要的所有的镜像;

(7) graphdriver将rootfs所有镜像,加载安装至Docker容器指定的文件目录下;

(8) 若以上操作全部正常执行,没有返回错误或异常,则Docker Client收到Docker Server返回状态之后,发起第二次HTTP请求。请求方

法为”POST”,请求URL为”/containers/”+container_ID+”/start”;

(9) Docker Server接受以上HTTP请求,并交给mux.Router,mux.Router通过URL以及请求方法来确定执行该请求的具体handler;

(10) mux.Router将请求路由分发至相应的handler,具体为PostContainersStart;

(11) 在PostContainersStart这个handler之中,名为”start”的job被创建,并开始执行;

(12) 名为”start”的job执行完初步的配置工作后,开始配置与创建网络环境,调用networkdriver;

(13) networkdriver需要为指定的Docker容器创建网络接口设备,并为其分配IP,port,以及设置防火墙规则,相应的操作转交至

libcontainer中的netlink包来完成;

(14) netlink完成Docker容器的网络环境配置与创建;

(15) 返回至名为”start”的job,执行完一些辅助性操作后,job开始执行用户指令,调用execdriver;

(16) execdriver被调用,初始化Docker容器内部的运行环境,如命名空间,资源控制与隔离,以及用户命令的执行,相应的操作转交至

libcontainer来完成;

(17) libcontainer被调用,完成Docker容器内部的运行环境初始化,并最终执行用户要求启动的命令。

以上是关于Docker的基本原理小结的主要内容,如果未能解决你的问题,请参考以下文章

(计算机组成原理)第三章存储系统-第二节1:基本的半导体原件和存储器芯片的原理

工具系列 | Docker基本概念小结

PCB 创建自己的原件库

计算机基础和操作系统基础小结

Docker镜像原理学习理解

altium designer画原理图怎么把单个原件放大缩小