ドッカー:アーキテクチャ分解

17分、簡単に見

内部ドッカーの構築

構築した内部ドッカーを理解するには、次の3つのコンポーネントと理解すべきで:

ドッカーイメージ(画像)

ドッカーコンテナ(コンテナ)

ドッカー倉庫(リポジトリ)

基本的に、我々はドッカーのライフサイクル全体を理解し、これらの3つの概念を理解しています。

1)ドッカーミラー(イメージ)

ドッカーイメージは、読み取り専用テンプレートです。例えば、ミラーは、完全なUbuntuのオペレーティングシステム環境、ユーザーがインストールする必要がある唯一のApacheや他のアプリケーションを含めることができます。ミラーリングは、ドッカーコンテナを作成するために使用することができます。またドッカーは、既存のミラーイメージを作成または更新するには、非常に単純なメカニズムを提供し、利用者にも使用を指示する他の人から直接、既製の画像をダウンロードすることができます。

2)ドッカー容器(コンテナ)

ドッカーは、アプリケーションを実行するための容器を使用しています。画像作成のインスタンスを実行してからのコンテナが、削除、停止、開始、開始することができます。各容器は、プラットフォームの安全性を確保するために、互いに分離されています。コンテナは、アプリケーション内で実行されている(root権限、プロセス空間、ユーザ空間とサイバースペース、などを含む)、Linux環境の簡易版として見ることができます。

注:画像は、読み取り専用で、容器を、それが最上位層として書き込み可能な層を作成するために開始したとき。

3)ドッカー倉庫(リポジトリ)

倉庫には、画像ファイルを格納するための中心的な場所です。時には、倉庫、倉庫、登録サーバ(レジストリ)が混同されます、厳密に分離しません。実際には、登録された倉庫サーバは、多くの場合、いくつかの倉庫が含まれ、各倉庫はまた、ミラーの数が含まれ、各ミラーは、異なる標識(タグ)を有します。

倉庫は公共倉庫(公立)、民間倉庫(プライベート)の二つの形式に分けられます。最大の公共倉庫ドッカーハブは、ダウンロードするためのユーザに利用可能な画像の膨大な数を格納します。国内の公共の倉庫がドッカープールなどが含まれ、より安定した本土のユーザーの迅速なアクセスを提供することができます。もちろん、ユーザーは、ローカルネットワーク内の民間倉庫を作成することができます。ユーザーが自分の画像を作成する場合、あなたは次の時間は、別のマシン上でこの画像を使用するだけで、その上に倉庫からプルダウンするので、パブリックまたはプライベート倉庫にアップロードするためにプッシュコマンドを使用することができます。

注:コンセプトはGitリポジトリとドッカー倉庫に似て、GitHubの登録サーバは、ホスティングサービスとして理解することができます。

 

ドッカー総分解アーキテクチャ

ドッカーは、C / Sモードの点でユーザのためのアーキテクチャ、後端ドッカーが非常に緩くアーキテクチャに結合され、モジュールがその職務を行い、有機組み合わせ、ドッカーの動作をサポートします。

ここでは、ドッカー全体的なアーキテクチャを同封しています:

これは、ユーザーがドッカークライアントドッカーデーモンが通信を確立する使用され、図から明らかであり、後者に要求を送信します。

本体部ドッカードッカーデーモンアーキテクチャ、最初に提供サーバー機能が要求ドッカークライアントを受け入れることを可能にする、エンジンは、各作業は、ジョブの存在の形である、内部作業ドッカーの一連を行います。

動作中のジョブが、必要なコンテナミラーとき、ドッカーレジストリから画像をダウンロードして、グラフの形で保存された画像をダウンロードすることにより、ミラー管理graphdriverを駆動し、あなたはネットワーク環境ドッカーを作成する必要がある場合、ネットワーク管理を介して駆動はnetworkdriverを作成しますおよびネットワーク環境ドッカーコンテナを構成し、ドッカーコンテナあなたが操作を実行するためのリソースユーザの指示などを実行する必要がある場合、execdriverによって行われます。

そして別の容器はnetworkdriverとexecdriver特定の操作は、コンテナlibcontainerによって達成され、libcontainer管理パックです。コマンドの実行中に、実際のドッカーコンテナを実行した後の容器を実行すると、コンテナは、別のファイルシステム、独立した安全な動作環境を持っています。

ドッカーのアーキテクチャと実現内の各モジュールの最初に、機能

次に、我々はドッカー全体的なアーキテクチャ図で開始され、様々なモジュールのフレームワーク、および各モジュール内の構造のより洗練された分析を引き出して機能が記載されています。主なモジュールは以下のとおりです。ドッカークライアント、ドッカーデーモン、ドッカーレジストリ、グラフ、ドライバー、libcontainerとドッカーコンテナ。

1.1)ドッカークライアント

ドッカークライアントアーキテクチャは、ドッキングウィンドウドッキングウィンドウデーモンとユーザーがクライアントとの通信を確立することです。ドッカーコマンドラインツールによってドッカーするためにユーザによって使用される実行可能ファイルは、コンテナ管理の多くの要求を開始することができます。

TCP://ホスト:ポート、UNIX:// path_to_socketとFD:// socketfdドッカークライアントの通信は、次の3つの方法とドッカーデーモンに確立することができます。簡単のため、すべての通信の両方について最初のプロトタイプの実施形態として本明細書中で使用されます。同時に、それはフラグラインが伝送のセキュリティを確保するために、コマンドトランスポート層セキュリティ(TLS)関連パラメータの設定パラメータを設定することにより、ドッカークライアントを形成してもよいドッカーデーモン送信要求との接続を確立します。

ドッカークライアント管理要求がドッカーデーモンによって受信され、ドッカークライアントが要求を受信し、対応する単純な処理を戻す要求を処理容器を送信した後、ドッカークライアントは、完全なライフサイクルが終わりました。あなたは、コンテナ管理要求を送信し続ける必要がある場合には、ユーザーがドッキングウィンドウの実行可能ファイルによってドッカークライアントを再作成する必要があります。

1.2)ドッカーデーモン

ドッカードッカーデーモンは、システム・アーキテクチャ、バックグラウンド・プロセスに常駐する、機能は次のとおり受け付け、処理はドッカークライアントが送信要求します。デーモンはバックグラウンドでサーバーを起動する、サーバーが送信された要求ドッカークライアントを受け入れるための責任があり、ルーティングや配信スケジュールを通じて要求、サーバーを受け取った後、要求を実行するための適切なハンドラを見つけます。

また、起動するために使用ドッカーデーモン実行可能ファイルは、同じ開始およびドッキングウィンドウのクライアントの実行可能ファイルを使用ドッキングウィンドウをドッキングウィンドウ。ドッカーコマンドがドッカーデーモンとドッカークライアントを決定するためにパラメータを渡すことによって、実行されたとき。

ドッカーサーバー、エンジンと仕事:ドッカーデーモンアーキテクチャは、3つの部分に分けることができます。以下のデーモンアーキテクチャ。

ドッカー:アーキテクチャ分解

1.3)ドッカーサーバー

ドッカーServerがドッカードッカークライアントアーキテクチャのサーバーにサービスを提供するように設計されています。サーバ機能は以下のとおりです。ドッカークライアントに送信スケジューリング要求を受け入れ、配布します。次の図のドッカーServerのアーキテクチャ。

起動時にドッカー、パケットゴリラ/ MUXオーバーは、ルーティング機能要求を提供し、mux.Routerを作成します。Golangでゴリラ/マルチプレクサ、強力なルータ、およびスケジューラのURLディスパッチャです。mux.Routerは、多数のルーティングエントリ、HTTPリクエストメソッド(PUT、POST、GETまたはDELETE)から各ルーティングエントリ、URL、ハンドラ三つの部分を追加しました。

終了mux.Router、ドッカーサーバアドレスを作成し、パラメータとしてmux.Routerリスニングの形態でドッカークライアントHTTPアクセスドッカーデーモン後であれば、httpSrv = http.Server {}、最終実行httpSrv.Serve()リクエストを作成しますサービス。

Serverのサービスプロセスでは、リスナーのServerインタビュー要求ドッカークライアント、および要求にサービスを提供するための新しいゴルーチンを作成します。ゴルーチンでは、最初の要求を読んで、その後、分析作業を行い、その後、対応するルーティングエントリを検索し、要求を処理するための適切なハンドラを呼び出し、最後にリクエストを処理した後、要求にハンドラー返信。

ことに注意してください:ドッカーServerが起動ドッカーの中に実行、ジョブを完了するために名付けられ、「serveapi」によって運営されています。原則として、実行ドッカーServerは、多くの仕事1の1ですが、ドッカーサーバーと後続のジョブサービスのための重要な特性の重要性を強調するために、「serveapiは」ドッカーサーバーとして理解ジョブの個別の分析を、引き抜きます。

1.4)エンジン

エンジンは、ランタイムエンジンドッカーアーキテクチャですが、また、コアモジュールの動作をドッキングウィンドウ。これは、役割ドッカーコンテナの保管倉庫を果たし、およびジョブ管理の実装の仕方によって、これらのコンテナを操作します。

在Engine数据结构的设计与实现过程中,有一个handler对象。该handler对象存储的都是关于众多特定job的handler处理访问。举例说明,Engine的handler对象中有一项为:{“create”: daemon.ContainerCreate,},则说明当名为”create”的job在运行时,执行的是daemon.ContainerCreate的handler。

1.5)Job

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

Job的设计者,把Job设计得与Unix进程相仿。比如说:Job有一个名称,有参数,有环境变量,有标准的输入输出,有错误处理,有返回状态等。

1.6)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.7)Graph

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

其中,GraphDB是一个构建在SQLite之上的小型图数据库,实现了节点的命名以及节点之间关联关系的记录。它仅仅实现了大多数图数据库所拥有的一个小的子集,但是提供了简单的接口表示节点之间的关系。

同时在Graph的本地目录中,关于每一个的容器镜像,具体存储的信息有:该容器镜像的元数据,容器镜像的大小信息,以及该容器镜像所代表的具体rootfs。

1.8)Driver

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

在Docker Driver的实现中,可以分为以下三类驱动:graphdriver、networkdriver和execdriver。

graphdriver主要用于完成容器镜像的管理,包括存储与获取。即当用户需要下载指定的容器镜像时,graphdriver将容器镜像存储在本地的指定目录;同时当用户需要使用指定的容器镜像来创建容器的rootfs时,graphdriver从本地镜像存储目录中获取指定的容器镜像。

在graphdriver的初始化过程之前,有4种文件系统或类文件系统在其内部注册,它们分别是aufs、btrfs、vfs和devmapper。而Docker在初始化之时,通过获取系统环境变量”DOCKER_DRIVER”来提取所使用driver的指定类型。而之后所有的graph操作,都使用该driver来执行。

graphdriver的架构如图

networkdriver的用途是完成Docker容器网络环境的配置,其中包括Docker启动时为Docker环境创建网桥;Docker容器创建时为其创建专属虚拟网卡设备;以及为Docker容器分配IP、端口并与宿主机做端口映射,设置容器防火墙策略等。networkdriver的架构如下图。

execdriver作为Docker容器的执行驱动,负责创建容器运行命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等。在execdriver的实现过程中,原先可以使用LXC驱动调用LXC的接口,来操纵容器的配置以及生命周期,而现在execdriver默认使用native驱动,不依赖于LXC。具体体现在Daemon启动过程中加载的ExecDriverflag参数,该参数在配置文件已经被设为”native”。这可以认为是Docker在1.2版本上一个很大的改变,或者说Docker实现跨平台的一个先兆。execdriver架构如下图:

1.9)libcontainer

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

正是由于libcontainer的存在,Docker可以直接调用libcontainer,而最终操纵容器的namespace、cgroups、apparmor、网络设备以及防火墙规则等。这一系列操作的完成都不需要依赖LXC或者其他包。libcontainer架构如下图:

另外,libcontainer提供了一整套标准的接口来满足上层对容器管理的需求。或者说,libcontainer屏蔽了Docker上层对容器的直接管理。又由于libcontainer使用Go这种跨平台的语言开发实现,且本身又可以被上层多种不同的编程语言访问,因此很难说,未来的Docker就一定会紧紧地和Linux捆绑在一起。而于此同时,Microsoft在其著名云计算平台Azure中,也添加了对Docker的支持,可见Docker的开放程度与业界的火热度。

暂不谈Docker,由于libcontainer的功能以及其本身与系统的松耦合特性,很有可能会在其他以容器为原型的平台出现,同时也很有可能催生出云计算领域全新的项目。

1.10)Docker container

Docker container(Docker容器)是Docker架构中服务交付的最终体现形式。

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

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

 

对于整个Docker的介绍先到这里,真正去理解Docker架构还需要多去实践Docker才行。

17分钟快速浏览一遍

Docker内部构建

要理解Docker内部构建,需要理解以下三种部件:

Docker镜像(Image)

Docker容器(Container)

Docker仓库(repository)

基本上理解了这三个概念,就理解了Docker的整个生命周期。

1)Docker镜像(Image)

Docker镜像就是一个只读的模板。比如,一个镜像可以包含一个完整的ubuntu操作系统环境,里面仅安装了apache或用户需要的其他应用程序。镜像可以用来创建Docker容器。另外Docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人哪里下载一个已经做好的镜像来直接使用。

2)Docker容器(Container)

Docker利用容器来运行应用。容器是从镜像创建的运行实例,它可以被启动、开始、停止、 删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

注:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。

3)Docker仓库(repository)

仓库是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈, 并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是Docker Hub, 存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,可以提供大陆用户更稳定快速的访问。当然,用户也可以在本地网络内创建一个私有仓库。当用户创建了自己的镜像之后就可以使用push命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上pull下来就可以了。

注:Docker仓库的概念跟Git类似,注册服务器可以理解为GitHub这样的托管服务。

 

Docker总架构分解

Docker对使用者来讲是一个C/S模式的架构,而Docker的后端是一个非常松耦合的架构,模块各司其职,并有机组合,支撑Docker的运行。

在此,先附上Docker总架构:

从上图不难看出,用户是使用Docker Client与Docker Daemon建立通信,并发送请求给后者。

而Docker Daemon作为Docker架构中的主体部分,首先提供Server的功能使其可以接受Docker Client的请求;而后Engine执行Docker内部的一系列工作,每一项工作都是以一个Job的形式的存在。

Job的运行过程中,当需要容器镜像时,则从Docker Registry中下载镜像,并通过镜像管理驱动graphdriver将下载镜像以Graph的形式存储;当需要为Docker创建网络环境时,通过网络管理驱动networkdriver创建并配置Docker容器网络环境;当需要限制Docker容器运行资源或执行用户指令等操作时,则通过execdriver来完成。

而libcontainer是一项独立的容器管理包,networkdriver以及execdriver都是通过libcontainer来实现具体对容器进行的操作。当执行完运行容器的命令后,一个实际的Docker容器就处于运行状态,该容器拥有独立的文件系统,独立并且安全的运行环境等。

一、Docker架构内各模块的功能与实现分析

接下来,我们将从Docker总架构图入手,抽离出架构内各个模块,并对各个模块进行更为细化的架构分析与功能阐述。主要的模块有:Docker Client、Docker Daemon、Docker Registry、Graph、Driver、libcontainer以及Docker container。

1.1)Docker Client

Docker Client是Docker架构中用户用来和Docker Daemon建立通信的客户端。用户使用的可执行文件为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发送的请求。该守护进程在后台启动了一个Server,Server负责接受Docker Client发送的请求;接受请求后,Server通过路由与分发调度,找到相应的Handler来执行请求。

Docker Daemon启动所使用的可执行文件也为docker,与Docker Client启动所使用的可执行文件docker相同。在docker命令执行时,通过传入的参数来判别Docker Daemon与Docker Client。

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

Docker:架构分解

1.3)Docker Server

Docker Server在Docker架构中是专门服务于Docker Client的server。该server的功能是:接受并调度分发Docker Client发送的请求。Docker Server的架构如下图。

在Docker的启动过程中,通过包gorilla/mux,创建了一个mux.Router,提供请求的路由功能。在Golang中,gorilla/mux是一个强大的URL路由器以及调度分发器。该mux.Router中添加了众多的路由项,每一个路由项由HTTP请求方法(PUT、POST、GET或DELETE)、URL、Handler三部分组成。

若Docker Client通过HTTP的形式访问Docker Daemon,创建完mux.Router之后,Docker将Server的监听地址以及mux.Router作为参数,创建一个httpSrv=http.Server{},最终执行httpSrv.Serve()为请求服务。

在Server的服务过程中,Server在listener上接受Docker Client的访问请求,并创建一个全新的goroutine来服务该请求。在goroutine中,首先读取请求内容,然后做解析工作,接着找到相应的路由项,随后调用相应的Handler来处理该请求,最后Handler处理完请求之后回复该请求。

需要注意的是:Docker Server的运行在Docker的启动过程中,是靠一个名为”serveapi”的job的运行来完成的。原则上,Docker Server的运行是众多job中的一个,但是为了强调Docker Server的重要性以及为后续job服务的重要特性,将该”serveapi”的job单独抽离出来分析,理解为Docker Server。

1.4)Engine

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

在Engine数据结构的设计与实现过程中,有一个handler对象。该handler对象存储的都是关于众多特定job的handler处理访问。举例说明,Engine的handler对象中有一项为:{“create”: daemon.ContainerCreate,},则说明当名为”create”的job在运行时,执行的是daemon.ContainerCreate的handler。

1.5)Job

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

Job的设计者,把Job设计得与Unix进程相仿。比如说:Job有一个名称,有参数,有环境变量,有标准的输入输出,有错误处理,有返回状态等。

1.6)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.7)Graph

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

其中,GraphDB是一个构建在SQLite之上的小型图数据库,实现了节点的命名以及节点之间关联关系的记录。它仅仅实现了大多数图数据库所拥有的一个小的子集,但是提供了简单的接口表示节点之间的关系。

同时在Graph的本地目录中,关于每一个的容器镜像,具体存储的信息有:该容器镜像的元数据,容器镜像的大小信息,以及该容器镜像所代表的具体rootfs。

1.8)Driver

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

在Docker Driver的实现中,可以分为以下三类驱动:graphdriver、networkdriver和execdriver。

graphdriver主要用于完成容器镜像的管理,包括存储与获取。即当用户需要下载指定的容器镜像时,graphdriver将容器镜像存储在本地的指定目录;同时当用户需要使用指定的容器镜像来创建容器的rootfs时,graphdriver从本地镜像存储目录中获取指定的容器镜像。

在graphdriver的初始化过程之前,有4种文件系统或类文件系统在其内部注册,它们分别是aufs、btrfs、vfs和devmapper。而Docker在初始化之时,通过获取系统环境变量”DOCKER_DRIVER”来提取所使用driver的指定类型。而之后所有的graph操作,都使用该driver来执行。

graphdriver的架构如图

networkdriver的用途是完成Docker容器网络环境的配置,其中包括Docker启动时为Docker环境创建网桥;Docker容器创建时为其创建专属虚拟网卡设备;以及为Docker容器分配IP、端口并与宿主机做端口映射,设置容器防火墙策略等。networkdriver的架构如下图。

execdriver作为Docker容器的执行驱动,负责创建容器运行命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等。在execdriver的实现过程中,原先可以使用LXC驱动调用LXC的接口,来操纵容器的配置以及生命周期,而现在execdriver默认使用native驱动,不依赖于LXC。具体体现在Daemon启动过程中加载的ExecDriverflag参数,该参数在配置文件已经被设为”native”。这可以认为是Docker在1.2版本上一个很大的改变,或者说Docker实现跨平台的一个先兆。execdriver架构如下图:

1.9)libcontainer

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

正是由于libcontainer的存在,Docker可以直接调用libcontainer,而最终操纵容器的namespace、cgroups、apparmor、网络设备以及防火墙规则等。这一系列操作的完成都不需要依赖LXC或者其他包。libcontainer架构如下图:

另外,libcontainer提供了一整套标准的接口来满足上层对容器管理的需求。或者说,libcontainer屏蔽了Docker上层对容器的直接管理。又由于libcontainer使用Go这种跨平台的语言开发实现,且本身又可以被上层多种不同的编程语言访问,因此很难说,未来的Docker就一定会紧紧地和Linux捆绑在一起。而于此同时,Microsoft在其著名云计算平台Azure中,也添加了对Docker的支持,可见Docker的开放程度与业界的火热度。

暂不谈Docker,由于libcontainer的功能以及其本身与系统的松耦合特性,很有可能会在其他以容器为原型的平台出现,同时也很有可能催生出云计算领域全新的项目。

1.10)Docker container

Docker container(Docker容器)是Docker架构中服务交付的最终体现形式。

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

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

 

对于整个Docker的介绍先到这里,真正去理解Docker架构还需要多去实践Docker才行。

おすすめ

転載: www.cnblogs.com/jpfss/p/10941789.html