Docker教程(3)理解Docker架构

Docker的主要组件


Docker有两个主要组件:

  • Docker引擎:开源的容器化平台;
  • Docker Hub:我们的用于分享和管理Docker容器的SAAS平台。

Docker的架构


Docker使用一个C/S架构。Docker客户端和Docker守护进程交流,Docker守护进程做非常重要的工作,构建,运行和分发你的Docker容器。Docker客户端和守护进程可以运行在同样的系统上,或者是你可以连接一个Docker客户端到一个远程Docker守护进程中。Docker客户端和守护进程通过sockets或通过RESTful API进行沟通交流。

Docker教程(3)理解Docker架构_第1张图片

Docker守护进程


正如上面的图片显示,Docker守护进程运行在一个主机机器中。用户不直接和守护进程交互,而是通过Docker客户端。

Docker客户端


Docker客户端,以docker二进制的形式出现,是Docker最基本的用户接口。他接收来自用户的命令,然后和Docker守护进程来回沟通。

Docker内部


为了能够理解Docker的内部,你需要去理解下面三个资源:

  • Docker镜像
  • Docker注册处
  • Docker容器
  • Docker镜像
Docker镜像

一个Docker镜像是一个只读的模板。例如,一个镜像可以包含一个带有Apache和你的web应用的Ubuntu操作系统。镜像被用来创建Docker容器。Docker提供了一个简单的方式来构建一个新的镜像或更新一个存在的镜像,或者是你可以下载其他人已经创建的Docker镜像。Docker镜像是Docker的build组件。

Docker注册处

Docker注册处保留镜像。这些是来自于上传或下载镜像的公共或私密存储的地方。公共的Docker注册处又Docker Hub提供。他提供了一个你可以使用的已存镜像的集合。这些可以是你自己创建的或其他人创建的你可以使用的镜像。Docker注册处是Docker的distribution组件。

Docker容器

Docker容器和目录是相似的。一个Docker容器可以保存任何东西,这些东西是运行一个应用程序所必须的。每一个容器都是从一个Docker镜像中创建的。Docker容器可以被运行,开启,停止,移动和删除。每一个容器都是一个分离的和安全的应用平台。Docker容器是Docker的运行组件。

Docker镜像如何工作


我们已经知道Docker镜像是一个只读的模板,在镜像中Docker容器被创建。每一个容器包含一系列层。Docker使用union文件系统来组合这些层到一个单一的镜像中。Union文件系统允许分离文件系统的文件和目录作为分支,被透明化的覆盖,构成一个单一的一致的文件系统。

Docker非常轻量化的一个原因就是因为这些层。当你改变了一个Docker镜像的时候–例如,更新一个应用程序到一个新版本–一个新的层被构建。因此,不是替换整个镜像或整体重新构建。就像你可能在一个虚拟机上工作,仅仅那一层被添加或更新。现在你不必发布一个整体的新的镜像,仅仅更新便可。这使得发布Docker镜像更快更简单。

每一个镜像都从一个基础镜像开始,例如,ubuntu,一个基本的Ubuntu镜像,或者是fedora,一个基本的Fedora镜像。你也可以使用你自己的镜像作为新镜像的基础镜像,例如,如果你有一个基本的Apache镜像,你可以使用这个作为你的Web应用镜像的基本镜像。

Docker镜像从这些基本镜像中使用一个简单的,可描述的步骤,我们称作指令,被构件。每一个指令在我们的镜像中创建一个新层。指令包含的行为类似于:

  • 运行一个命令
  • 添加一个文件或目录
  • 创建一个环境变量
  • 当从这个镜像中创建了一个容器的时候哪一个进程运行

这些指令被存储在被称为Dockerfile的文件中。一个Dockerfile是一个基于包含构件镜像的指令和命令脚本的文本文件。当你需要构件一个镜像,执行指令返回一个最终镜像的时候,Docker读取这个Dockerfile。

Docker注册处如何工作


Docker注册处是你的Docker镜像的保存处。一旦你构建了一个Docker镜像,你可以将他推送到一个公共的注册处例如Docker Hub或者是到你自己的注册处。

使用Docker客户端,你可以搜索已经发布的镜像和下载到你的Docker主机中来从他们中构建容器。

Docker Hub既提供公共的也提供私人的镜像存储。公共存储可以被任何人搜索和下载。私人存储仅仅你和你的用户可以下载使用。

容器如何工作


一个容器包含一个操作系统,用户文件和元数据。正如我们看到的,每一个容器都是从镜像中被构建的。那个镜像告诉Docker容器保存什么数据,当容器发布的时候运行什么进程,还有其他一些配置数据。Docker镜像是只读的。当Docker从一个镜像中运行一个容器的时候,他在镜像的最顶层添加一个读写层(使用union文件系统),在该层中你的应用程序可以运行。

当你运行一个容器的时候发生了啥


无论是使用docker二进制还是API,Docker客户端告诉Docker守护程序来运行一个容器。

$ docker run -i -t ubuntu /bin/bash

Docker引擎客户端使用带有run选项的docker二进制运行一个新的容器。Docker客户端需要告诉Docker守护进程运行容器的最低限度是:

  • 容器从哪一个Docker镜像中构建的,例如,ubuntu
  • 当他被发布的时候,内部容器想要运行的命令,例如,/bin/bash

所以,当我们运行这个命令的时候钩子下面发生了什么?

按照次序,Docker引擎做:

  • 推出ubuntu镜像:Docker引擎检查当前的ubuntu镜像。如果镜像已经存在,Docker引擎使用他作为新的容器。如果在当前主机上不存在,然后Docker引擎从Docker Hub中拉取下来;
  • 创建一个新的容器:一旦Docker引擎有镜像,他便使用它来创建一个容器;
  • 分配文件系统,挂载一个读写层:容器在文件系统中被创建,并且一个读写层被添加到镜像中;
  • 分配一个网络/桥接口。创建一个网络接口来允许Docker容器与本地主机交流;
  • 设置一个IP地址。从一个池中寻找和绑定一个可用的IP地址;
  • 执行一个你指定的进程。运行应用;
  • 捕获和获取应用输出:连接和记录标准输入,输出和错误,来告诉你你的应用是如何工作的;
  • 现在你就拥有一个运行的容器了。现在你可以管理你的容器,与你的应用交互,当结束的时候,可以停止和移除你的容器。

底层的技术


Docker是使用Go编写的,使用多个内核特征来分发其功能。

命名空间


Docker充分使用称为namespace的技术来提供分离的工作空间,我们称为容器。当你运行一个容器,Docker为这个容器创造一些列命名空间。

这个提供了一层分离:容器的每一个方面运行在他自己的明明空间中,并且不能访问其命名空间之外的数据。

Docker引擎在Linux中使用的命名空间有:

  • pid命名空间:进程分离;
  • net命名空间:管理网络接口;
  • ipc命名空间:管理IPC资源访问;
  • mnt命名空间:管理挂载点;
  • uts命名空间:分离内核和版本识别。

控制组


在Linux上的Docker引擎也会使用其他的技术称为cgroups或控制组。在分离体中运行程序的关键就是只让他们使用你想要的资源。这能保证容器在主机中是一个优秀的多租户居民。控制组允许Docker引擎共享可用硬件资源,如果必要,设置限制和约束。例如,为特定容器限制可用内存。

Union文件系统


Union文件系统或者是UnionFS,是一个文件系统,其通过创建层来操作,使得他们更加轻量化和快速。Docker引擎使用union文件系统来为容器提供构件块。Docker引擎可以使用多个union文件系统变量,包括AUFS,btrfs,vfs和DeviceMapper。

容器格式


Docker引擎组合这些组件到一个包中,我们称为一个容器格式。默认的容器格式被称为libcontainer。在将来,Docker可能支持其他容器格式,例如,通过集成BSD Jails或Solaris Zones。

你可能感兴趣的:(Docker)