(最后修改时间 —— 2019.8.20 / 撰写人:Kenllf / 转载请注明出处 / 本文已完成)
容器,是由 代码 与其 运行所需的依赖 [1] 打包而成的一个标准化单元。使用容器,可以让我们很 快速 且 可靠 地将应用从一个开发环境 转移 到另一个开发环境 [2]。Docker 容器镜像 [3],是软件的一个 轻量、独立的且可执行的包。它包含了一个应用运行所需的一切 —— 包括 代码、运行时(runtime)、系统工具、系统库和配置等。
注:
[1]:指环境变量,系统库之类的
[2]:例如,将一个 应用/软件 从一个 Windows 转到另一个 Windows,或者从 Windows 转到 Linux 之类的情况。原本还需要重新配环境,安装依赖什么的,使用容器可以省去这些麻烦。而且原本往往重新配置环境什么的也很麻烦,能不能配成功也难说,而使用容器技术就不会有这些顾虑
[3]:对虚拟机有了解的,可以将 Docker 容器镜像 类比虚拟机的镜像。当我们在一台电脑创建好容器之后,可以创建其相应的镜像,然后在新的电脑上部署好镜像后,即可使用,不必再配什么环境。
容器 是 动态 的,容器镜像 是 静态 的,它们关系很简单,不用想复杂了。以 Docker 容器 举例 —— 当 Docker 镜像 运行 在 Docker 引擎 上时,它就成为了一个 容器。是不是很简单!而且发展到现在,容器技术已经支持 Linux 和 Windows 的应用了 [4],不管 底层设施 [5] 如何,容器化的软件 都一样可以运行。容器将 软件 和它周围的 运行环境 隔绝开 [6],确保即使开发阶段和发行阶段存在差异,软件一样能运行。
注:
[4]:曾经只有 Linux 有自己的容器技术,后来容器技术发展起来并大火之后,Windows 也开始发展自己的容器技术。
[5]:这里所说的 底层设施 是指 硬件设施 等。
[6]:容器中已经包含软件正常运行所需的一切,前面已经讲解过了。所以 软件 和 外部环境 隔绝开 不会 对软件的正常运行产生影响。相反,当容器内部崩溃,或是容器外部环境崩溃,它们之间不会相互影响。这也是容器技术最初的目的 —— 为了防止某个软件运行发生问题影响到整个系统,就将该软件部署到容器中。而 “Build Once, Run Anywhere”(一次编写,到处运行),则是容器技术后来发展的成果,这也是 Docker 大火的一个原因。
运行在 Docker 引擎 上的 Docker 容器 的特点:
[7]:这个内核就是最原本的操作系统(OS)的内核,所以实际上容器内外的软件都是共用这一个内核。
[8]:想想虚拟机的虚拟化方式,就是重新打造一个操作系统,让软件运行在新的操作系统之上。可想而知,虚拟机的方式会消耗更多的资源。容器与之对比,真的轻量许多。
[9]:相对虚拟机而言,容器的隔离效果是会差一些。因为虚拟机是从操作系统到上层软件全部隔离了,显然更加彻底。但是 Docker 容器也足够安全了,国内在使用的大公司也不少 —— 像 腾讯、京东、美团、新浪、大众点评等很早就有在使用了,国外使用 Docker 容器的公司就更多了。
图中最下面的是 底层设施(Infrastructure)。在其之上是 主机操作系统(Host Operating System),这就是我们平常在使用的操作系统,可能是 Windows 或者 Linux。这两层都是公共的部分,也是最原始的,不需要改变的。
在 主机操作系统(Host Operating System),我们先运行 Docker 引擎 [10],然后就可以在 Docker 引擎 中打开 Docker 镜像,Docker 引擎 就会自动帮我们创建出 Docker 容器。图中 应用 A(App A) 到 应用 F(App F) 都分别是一个独立的容器。
容器就是这样一个简单的概念。具体的实现原理还是有些复杂的,但是对于我们使用者来说,能够了解它的基本原理,知道它的优缺点,知道如何使用,就完全足够了。毕竟我们不是要开发 Docker 引擎,我们只是要使用它 [11]。
[10]:Docker 引擎 就是图中 Docker 的那一层。运行 Docker 引擎 这一步跟我们平常运行任何一个软件没有任何区别。
[11]:但是也欢迎有志向,有能力的开发者们,参与到 Docker 的开发中。Docker 的开源项目名称已经从原来的 Docker 更改为 moby 了。但其实 moby 就是原来的 Docker 开源项目,没两样。Docker 开源项目之所以更名为 moby,外界都说是 Docker 公司 为了将 Docker 的流量引到自己公司来。所以现在 Docker 开源项目的地址是:https://github.com/Moby/moby
Docker 容器技术 在 2013 年以一个 开源 的 Docker 引擎 正式发行。
它利用了当时已有的容器概念,特别是 Linux 领域中的容器概念。比如说 cgroups(control groups) 和 namespaces [12] 的 原语(primitives) [13]。Docker 的技术的独特之处来自于,它专注于解决开发者和系统操作者关于 将应用的依赖从基础设施(infrastructure)中独立出来 的需求。
[12]:cgroups 和 namespaces 都在容器技术上起了重要的作用。cgroups 主要用于资源管理,而 namespaces 用于隔离不同的程序,可以理解为每个容器有独立的 namespace。
[13]:原语(primitives)在计算机中是指不可拆分的操作,或者说原子操作。
容器技术在 Linux 领域的成功 [14],推动了 Docker 和 微软 的合作。这一合作也将 Docker 容器 和它强大的功能带到了 Windows 服务器 上(有时也成为 Docker Windows 容器)。
[14]:或者说是 Docker 在 Linux 容器虚拟化领域的成功,推动了它们之间的合作。因为 Linux 领域的容器虚拟化技术早在 Docker 之前就存在了,而 Docker 是让 Linux 的容器虚拟化技术更易于使用,可以说 Linux 容器虚拟化的大火就是 Docker 直接推动的。
Docker 及其开源项目 Moby [15] 提供的技术,已经被很多主要的数据中心提供商和云提供商所采用。这些提供商很多都把 Docker 作为他们的容器本地 IaaS 产品 [16]。此外,领先的开源无服务器框架也都采用 Docker 的容器技术
[15]:前面提到过,开源项目 Moby 其实就是原来的开源项目 Docker,只是后来改名了,内容还是原来的内容,而且一直在发展中。Docker 公司为了将 “Docker” 这个名称的流量引到自己公司,无耻的将开源项目改名了 -_-
[16]:比较拗口。首先 IaaS 是 基础设施即服务,这种服务的特点是,把 IT 基础设施作为一种服务通过网络对外提供。注意,是通过网络,不是真的卖硬件。相当于我们可以通过网络访问到他们的硬件资源,并且进行利用。这种情况下,Docker 就可以作为一个快速部署的利器。
容器和虚拟机都有资源隔离和分配的优势。但是他们的运作方式不一样 —— 因为容器是对 操作系统 虚拟化 [17],而虚拟机是对 硬件 进行虚拟化 [18]。所以比较起来,容器更轻便,也更高效。
[17]:对操作系统虚拟化,是指,对于容器内部的软件来说,它看起来像是拥有自己的操作系统(其实它没有,容器骗它说有)。而容器内部的创建和运行都是基于这个 “自己的操作系统” 的。
[18]:对硬件虚拟化,是指,对于虚拟机内部来说,它看起来像是拥有自己的硬件系统(其实它也没有,虚拟机骗它说有 =_=)。而虚拟机内部,包括操作系统的创建和系统的运行,都是基于这个 “自己的硬件系统” 的。所以虚拟化就像是一个童话,而童话里都是骗人的。
[19]:用户空间可以这么理解 —— 当我们打开电脑时,需要选择用户,或者输入密码,随后进入的就是一个用户空间。所以显然一台电脑上的容器都是在同一个用户空间的。现在来看虚拟机 —— 当我们打开虚拟机时,我们还要重复一次平常开电脑时,选用户或者输密码的过程,因为进入的是一个新的用户空间。
[20]:所谓相互隔离,简单理解就是容器中的应用觉得它就是唯一的应用,它对容器外的情况一无所知。容器起的就是一个隔离地作用。
[21]:奇怪,不是只需一个操作系统,也不需要用虚拟机吗?其实这里是从整个宏观来看 —— 比如说以一整个公司,或者是一群用户来看,使用容器的情况下,确实整体对虚拟机和操作系统的需求下降了(所谓下降是和原来虚拟机时代对比)。
[22]:比如在一个服务器上安装 3 个虚拟机,那么服务器就相当于 1 个变成 3 个了,可以给更多的客户独立使用。
虽然听起来容器似乎比虚拟机要好上很多,但是容器要完全淘汰虚拟机还不太可能。其实容器和虚拟机组合使用,能大大地提升部署和管理应用(App)的灵活性。
如今云服务器已经很普及,而计算资源也相当丰富。如果按照一个服务器只有一个操作系统,那么大量计算资源就会被闲置,很浪费。由于服务器的性能要比家用电脑好很多,即使在上面安装一定量的虚拟机,每台虚拟机的性能也做够普通用户使用。再在虚拟机上安装容器,就可以很好地利用到容器带来的好处。