我一直在反复阅读Docker文档,试图理解Docker和完整虚拟机之间的差异。它如何能够在不增加负担的情况下提供完整的文件系统、隔离的网络环境等?
为什么将软件部署到Docker镜像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
Docker最初使用Linux容器(LXC),但后来切换到runC(以前称为libcontainer),它在与主机相同的操作系统上运行。这允许它共享许多主机操作系统资源。此外,它使用分层文件系统([AuFS](http://aufs.sourceforge.net/))并管理网络。
AuFS是分层文件系统,因此您可以拥有一个只读部分和一个写入部分,它们合并在一起。您可以将操作系统的公共部分设置为只读(并在所有容器之间共享),然后为每个容器分配自己的挂载以进行写入。
例如,如果您有一个1 GB的容器映像; 如果您想使用完整的VM,您需要将1 GB x数量的VMs。使用Docker和AuFS,您可以在所有这些容器之间共享大部分1 GB,并且即使有1000个容器,您仍然可能只有略超过1 GB的容器操作系统空间(假设它们都运行相同的OS映像)。
完整的虚拟化系统会为自己分配一组资源,并进行最少的共享。您获得更多的隔离,但这要重得多(需要更多的资源)。 Docker让您获得更少的隔离,但容器轻便(需要更少的资源)。因此,您可以在主机上轻松运行数千个容器,甚至都不会引起注意。尝试使用Xen做到这一点,除非您有一个非常大的主机,否则我认为这是不可能的。
完整的虚拟化系统通常需要几分钟才能启动,而Docker / LXC / runC容器只需要几秒钟,甚至有时不到一秒钟。
每种类型的虚拟化系统都有其优缺点。 如果您想要完全隔离且保证资源充足的完整虚拟机,那就是要走的路。 如果您只是想要将进程彼此隔离并在合理大小的主机上运行大量内容,那么Docker / LXC / runC似乎是要走的路。
有关更多信息,请查看这篇博客文章集合,它很好地解释了LXC是如何工作的(http://web.archive.org/web/20150326185901/http://blog.dotcloud.com/under-the-hood-linux-kernels-on-dotcloud-part )。
为什么将软件部署到docker映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
部署一致的生产环境说起来容易做起来难。 即使您使用Chef和Puppet等工具,主机和环境之间的OS更新和其他更改也总是存在的。
Docker使您能够将操作系统快照为共享映像,并使其易于在其他Docker主机上进行部署。本地开发,QA,生产等:所有相同的映像。当然,您可以使用其他工具执行此操作,但不如简单或快速。
这对于测试非常有用; 假设您有数千个测试需要连接到数据库,并且每个测试都需要数据库的原始副本并对数据进行更改。传统的方法是在每次测试后重置数据库,可以使用自定义代码或Flyway之类的工具 - 这可能会非常耗时,意味着测试必须串行运行。但是,使用Docker,您可以创建数据库映像并运行每个测试一个实例,然后并行运行所有测试,因为它们都知道它们都将针对相同数据库快照运行。由于测试在Docker容器中并行运行并且在容器中运行,因此它们可以在同一台主机上同时运行并应该更快完成。尝试使用完整的VM做到这一点。
好的,让我解释一下。您从一个基础映像开始,然后进行更改,并使用docker提交这些更改,它会创建一个映像。此映像仅包含与基础映像的差异。当您想要运行映像时,还需要基础映像,它使用分层文件系统将映像堆叠在基础映像的上方:如上所述,Docker使用AuFS。AuFS将不同的层合并在一起,您就可以得到所需的结果;您只需要运行它即可。您可以继续添加越来越多的映像(层),它将继续只保存差异。由于Docker通常建立在注册表上的现成映像之上,因此您很少需要自己“快照”整个操作系统。