《容器技术系列》一1.3 Docker各模块功能与实现分析

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 本节书摘来华章计算机《容器技术系列》一书中的第1章 ,第1.3节,孙宏亮 著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。 1.3 Docker各模块功能与实现分析 下面我们将从Docker的总架构图入手,抽离出架构内的各个模块,并对各个模块进行更为细化的架构分析与功能阐述。

本节书摘来华章计算机《容器技术系列》一书中的第1章 ,第1.3节,孙宏亮 著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

1.3 Docker各模块功能与实现分析

下面我们将从Docker的总架构图入手,抽离出架构内的各个模块,并对各个模块进行更为细化的架构分析与功能阐述。

1.3.1 Docker Client

Docker Client是Docker架构中用户与Docker Daemon建立通信的客户端。在一台安装有Docker的机器上,用户可以使用可执行文件docker作为Docker Client,发起众多Docker容器的管理请求。
Docker Client可以通过以下三种方式和Docker Daemon建立通信,分别为:tcp://host:port、unix://path_to_socket和fd://socketfd。为简单起见,本书主要使用第一种方式作为讲述两者通信的原型。通信方式确定后,DockerClient与Docker Daemon建立连接并传输请求时,可以通过命令行flag参数的形式,设置安全传输层协议(TLS)的有关参数,保证传输的安全性。
Docker Client发送容器管理请求后,请求由Docker Daemon接收并处理,当Docker Client接收到返回的请求响应并做简单处理后,Docker Client一次完整的生命周期就此结束。若需要继续发送容器管理请求,用户必须再次通过可执行文件docker创建Docker Client,并走完以上相同的流程。

1.3.2 Docker Daemon

Docker Daemon是Docker架构中一个常驻在后台的系统进程。所谓的“运行Docker”,即代表运行Docker Daemon。总之,DockerDaemon的作用主要有以下两方面:
接收并处理Docker Client发送的请求。
管理所有的Docker容器。
Docker Daemon运行时,会在后台启动一个Server,Server负责接收Docker Client发送的请求;接收请求后,Server通过路由与分发调度,找到相应的Handler来处理请求。
启动Docker Daemon所使用的可执行文件同样是docker,与Docker Client启动所使用的可执行文件docker相同。既然Docker Client与Docker Daemon都可以通过docker二进制文件创建,那么如何辨别两者就变得非常重要。实际上,执行docker命令时,通过传入的参数可以辨别Docker Daemon与Docker Client,如docker –d代表Docker Daemon的启动,dockerps则代表创建Docker Client,并发送ps请求。
Docker Daemon的架构大致可以分为三部分:Docker Server、Engine和Job。Daemon的架构如图1-2所示。

  1. Docker Server
    Docker Server在Docker架构中专门服务于Docker Client,它的功能是接收并调度分发Docker Client发送的请求。Docker Server的架构如图1-3所示。


image

在Docker Daemon的启动过程中,DockerServer第一个完成。Docker Server通过包gorilla/mux,创建了一个mux.Router路由器,提供请求的路由功能。在Go语言中,gorilla/mux是一个强大的URL路由器以及调度分发器。创建路由器之后,Docker Server为mux.Router中添加有效的路由项,每一个路由项由HTTP请求方法(PUT、POST、GET或DELETE)、URL和Handler三部分组成。
由于Docker Client通过HTTP协议访问Docker Daemon,故DockerServer创建完mux.Router之后,将Server的监听地址以及mux.Router作为参数,创建一个httpSrv=http.Server{},最终执行httpSrv.Serve()开始服务于外部请求。
在服务过程中,Docker Server在listener上接收Docker Client的访问请求。对于每一个Docker Client请求,DockerServer均会创建一个全新的goroutine来服务。在goroutine中,Docker Server首先读取请求内容,然后做请求解析工作,接着匹配相应的路由项,随后调用相应的Handler来处理,最后Handler处理完请求之后给Docker Client回复响应。
需要注意的是:Docker Server在Docker的启动过程中运行,通过一个名为“serveapi”的Job来实现。理论上,Docker Server的运行只是众多Job中的一个,但是为了强调Docker Server的重要性以及它为后续Job服务的重要特性,本书将“serveapi”的Job单独抽离出来分析,理解为Docker Server。

  1. Engine
    Engine是Docker架构中的运行引擎,同时也是Docker运行的核心模块。Engine存储着大量的容器信息,同时管理着Docker大部分Job的执行。换言之,Docker中大部分任务的执行都需要Engine协助,并通过Engine匹配相应的Job完成Job的执行。

在Docker源码中,有关Engine的数据结构定义中含有一个名为handlers的对象。该handlers对象存储的是关于众多特定Job各自的处理方式handler。举例说明,Engine的handlers对象中有一项为:{"create": daemon.ContainerCreate,},则说明当执行名为“create”的Job时,执行的是daemon.ContainerCreate这个handler。
除了容器管理之外,Engine还接管Docker Daemon的某些特定任务。当Docker Daemon遭遇到自身进程需要退出的情况时,Engine还负责完成DockerDaemon退出前的所有善后工作。

  1. Job
    Job可以认为是Docker架构中Engine内部最基本的工作执行单元。DockerDaemon可以完成的每一项工作都会呈现为一个Job。例如,在Docker容器内部运行一个进程,这是一个Job;创建一个新的容器,这是一个Job;在网络上下载一个文档,这是一个Job;包括之前在Docker Server部分谈及的,创建Server服务于HTTP协议的API,这也是一个Job,等等。

有关Job接口的设计,与UNIX进程非常相仿。比如说,Job有一个名称,有运行时参数,有环境变量,有标准输入与标准输出,有标准错误,还有返回状态等。
对于Job而言,定义完毕之后,运行才能完成Job自身真正的使命。Job的运行函数Run()则用以执行Job本身。

1.3.3 Docker Registry

Docker Registry是一个存储容器镜像(Docker Image)的仓库。容器镜像(Docker Image)是容器创建时用来初始化容器rootfs的文件系统内容。Docker Registry将大量的容器镜像汇集在一起,并为分散的Docker Daemon提供镜像服务。
Docker的运行过程中,有三种情况可能与Docker Registry通信,分别为搜索镜像、下载镜像、上传镜像。这三种情况所对应的Job名称分别为search、pull和push。
不同场景下,Docker Daemon可以使用不同的Docker Registry。公有Registry与私有Regsitry就是两种场景模式不同的Docker Registry。其中,大家熟知的Docker Hub,就是全球范围内最大的公有Registry。Docker可以通过互联网访问Docker Hub,并下载容器镜像;同时Docker也允许用户构建本地私有Registry,使容器镜像的获取在内网完成。

1.3.4 Graph

Graph在Docker架构中扮演的角色是容器镜像的保管者。不论是Docker下载的镜像,还是Docker构建的镜像,均由Graph统一化管理。由于Docker支持多种不同的镜像存储方式,如aufs、devicemapper、Btrfs等,故Graph对镜像的存储也会因以上种类而存在一些差异。对Docker而言,同一种类型的镜像被称为一个repository,如名称为ubuntu的镜像都同属一个repository;而同一个repository下的镜像则会因tag存在差异而不同,如ubuntu这个repository下有tag为12.04的镜像,也有tag为14.04的镜像。Docker中Graph的架构如图1-4所示。

image


本书对Graph以及容器镜像(Docker Image)的分析将以aufs为主,并在第8章进行深入分析。

1.3.5 Driver

Driver是Docker架构中的驱动模块。通过Driver驱动,Docker可以实现对Docker容器运行环境的定制,定制的维度主要有网络环境、存储方式以及容器执行方式。需要注意的是,Docker运行的生命周期中,并非用户所有的操作都是针对Docker容器的管理,同时包括用户对Docker运行信息的获取,还包括Docker对Graph的存储与记录等。因此,为了将仅与Docker容器有关的管理从Docker Daemon的所有逻辑中区分开来,Docker的创造者设计了Driver层来抽象不同类别各自的功能范畴 。
Docker Driver的实现可以分为以下三类驱动:graphdriver、networkdriver和execdriver。
graphdriver主要用于完成容器镜像的管理,包括从远程Docker Registry上下载镜像并进行存储,也包括本地构建完镜像后的存储。当用户下载指定的容器镜像时,graphdriver将容器镜像分层存储在本地的指定目录下;同时当用户需要使用指定的容器镜像来创建容器时,graphdriver从本地镜像存储目录中获取指定的容器镜像,并按特定规则为容器准备rootfs;另外,当用户需要通过指定Dockerfile构建全新镜像时,graphdriver会负责新镜像的存储管理。
在graphdriver的初始化过程之前,有4种文件系统或类文件系统的驱动Driver在DockerDaemon内部注册,它们分别是aufs、btrfs、vfs和devmapper。其中,aufs、btrfs以及devmapper用于容器镜像的管理,vfs用于容器volume的管理。Docker在初始化之时,优先通过获取系统环境变量“DOCKER_DRIVER”来提取所使用driver的指定类型。因此,之后所有的Graph操作,都使用该driver来执行。Docker镜像是Docker技术中非常关键的。2014年12月,在Linux 3.18-rc2版本中OverlayFS被合并至Linux内核主线,在Docker 1.4.0版本发布时,Docker官方宣布支持overlay这一类graphdriver,即用户在启动Docker Daemon时可以选择制定graphdriver的类型为overlay。graphdriver的架构如图1-5所示。

image


networkdriver的作用是完成Docker容器网络环境的配置,其中包括Docker Daemon启动时为Docker环境创建网桥;Docker容器创建前为其分配相应的网络接口资源;以及为Docker容器分配IP、端口并与宿主机做NAT端口映射,设置容器防火墙策略等。networkdriver的架构如图1-6所示。

image


execdriver作为Docker容器的执行驱动,负责创建容器运行时的命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等。在Docker 0.9.0版本之前,execdriver只能通过LXC驱动来实现容器的启动管理。实际上,当时Docker通过LXC驱动调用Linux下的LXC工具管理容器的创建,并控制管理容器的生命周期。从Docker 0.9.0开始,在继续支持LXC的情况下,Docker的execdriver默认使用native驱动,native驱动完全独立于LXC,属于Docker项目下第一个全新的子项目,用于容器的创建与管理。Docker 默认使用native驱动的具体体现为:Docker Daemon启动过程中加载的ExecDriverflag参数在配置文件中已经被设为native。native这个execdriver的存在,使得Docker对Linux容器的创建与管理有了自己的解决方案。execdriver架构如图1-7所示。

image

1.3.6 libcontainer

libcontainer是Docker架构中一个使用Go语言设计实现的库,设计初衷是希望该库可以不依靠任何依赖,直接访问内核中与容器相关的系统调用。
正是由于libcontainer的存在,Docker可以直接调用libcontainer,而最终操作容器的namespaces、cgroups、apparmor、网络设备以及防火墙规则等。这一系列操作的完成都不需要依赖LXC或者其他包。libcontainer架构如图1-8所示。

image


另外,libcontainer提供了一整套标准的接口来满足上层对容器管理的需求。或者说,libcontainer屏蔽了Docker上层对容器的直接管理。又由于libcontainer使用Go这种跨平台的语言开发实现,且本身又可以被上层多种不同的编程语言访问,因此,很难说未来的Docker一定会与Linux平台紧紧捆绑在一起。Docker Daemon的逻辑完全有可能位于其他非Linux操作系统的平台上,仅仅通过libcontainer的远程调用来实现对Docker容器的管理。另一方面,libcontainer与Docker Daemon的松耦合设计,似乎让用户感受到了除Linux Container 之外其他的容器技术接入Docker Daemon的可能性。libcontainer承接Linux内核与Docker Daemon的同时,也让Docker的生态在跨平台方面充满生机。与此同时,Microsoft在其著名云计算平台Azure中,也添加了对Docker的支持,可见Docker的开放程度与业界的火热度。
暂不谈Docker,由于本身完善的功能以及与应用系统的松耦合特性,libcontainer很有可能会在众多其他以容器为原型的平台出现,同时也很有可能催生出云计算领域全新的项目。

1.3.7 Docker Container

Docker Container(Docker容器)是Docker架构中服务交付的最终体现形式。Docker通过DockerDaemon的管理,libcontainer的执行,最终创建Docker容器。Docker容器作为一个交付单位,功能类似于传统意义上的虚拟机(Virtual Machine),具备资源受限、环境与外界隔离的特点。然而,实现手段却与KVM、Xen等传统虚拟化技术大相径庭。
Docker容器的从无到有,涉及Docker利用到的很多技术。总而言之,用户可以根据自己的需求,通过Docker Client向Docker Daemon发送容器的创建与启动请求,请求中将携带容器的配置信息,从而达到定制相应Docker容器的目的。用户对Docker容器的配置有以下4个基本方面:
通过指定容器镜像,使得Docker容器可以自定义rootfs等文件系统。
通过指定物理资源的配额,如CPU、内存等,使得Docker容器使用受限的物理资源。
通过配置容器网络及其安全策略,使得Docker容器拥有独立且安全的网络环境。
通过指定容器的运行命令,使得Docker容器执行指定的任务。

image

相关实践学习
通过容器镜像仓库与容器服务快速部署spring-hello应用
本教程主要讲述如何将本地Java代码程序上传并在云端以容器化的构建、传输和运行。
Kubernetes极速入门
Kubernetes(K8S)是Google在2014年发布的一个开源项目,用于自动化容器化应用程序的部署、扩展和管理。Kubernetes通常结合docker容器工作,并且整合多个运行着docker容器的主机集群。 本课程从Kubernetes的简介、功能、架构,集群的概念、工具及部署等各个方面进行了详细的讲解及展示,通过对本课程的学习,可以对Kubernetes有一个较为全面的认识,并初步掌握Kubernetes相关的安装部署及使用技巧。本课程由黑马程序员提供。   相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
8天前
|
Kubernetes 监控 开发者
掌握容器化:Docker与Kubernetes的最佳实践
【10月更文挑战第26天】本文深入探讨了Docker和Kubernetes的最佳实践,涵盖Dockerfile优化、数据卷管理、网络配置、Pod设计、服务发现与负载均衡、声明式更新等内容。同时介绍了容器化现有应用、自动化部署、监控与日志等开发技巧,以及Docker Compose和Helm等实用工具。旨在帮助开发者提高开发效率和系统稳定性,构建现代、高效、可扩展的应用。
|
4天前
|
关系型数据库 MySQL API
|
4天前
|
Java 应用服务中间件 Linux
【Docker容器化技术】docker安装与部署、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库
本文主要讲解了Docker的安装与部署、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库以及Docker容器虚拟化与传统虚拟机比较。
【Docker容器化技术】docker安装与部署、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库
|
6天前
|
JavaScript 持续交付 Docker
解锁新技能:Docker容器化部署在微服务架构中的应用
【10月更文挑战第29天】在数字化转型中,微服务架构因灵活性和可扩展性成为企业首选。Docker容器化技术为微服务的部署和管理带来革命性变化。本文探讨Docker在微服务架构中的应用,包括隔离性、可移植性、扩展性、版本控制等方面,并提供代码示例。
33 1
|
8天前
|
Docker 容器
docker 修改容器内的系统时间
【10月更文挑战第27天】docker 修改容器内的系统时间
145 2
|
14天前
|
Web App开发 iOS开发 Docker
Docker 容器的日志
【10月更文挑战第31天】
26 5
|
13天前
|
Kubernetes Cloud Native 开发者
云原生技术入门:Kubernetes和Docker的协作之旅
【10月更文挑战第22天】在数字化转型的浪潮中,云原生技术成为推动企业创新的重要力量。本文旨在通过浅显易懂的语言,引领读者步入云原生的世界,着重介绍Kubernetes和Docker如何携手打造弹性、可扩展的云环境。我们将从基础概念入手,逐步深入到它们在实际场景中的应用,以及如何简化部署和管理过程。文章不仅为初学者提供入门指南,还为有一定基础的开发者提供实践参考,共同探索云原生技术的无限可能。
22 3
|
14天前
|
存储 缓存 Docker
docker中挂载数据卷到容器
【10月更文挑战第16天】
21 2
|
5天前
|
Docker 容器
docker 容器重启
【10月更文挑战第30天】docker 容器重启
10 0
|
20天前
|
存储 Docker 容器
docker中挂载数据卷到容器
【10月更文挑战第12天】
56 5