题 Docker与虚拟机有何不同?


我一直在重读 Docker文档 试图了解Docker和完整VM之间的区别。它如何设法提供完整的文件系统,隔离的网络环境等,而不是那么重?

为什么将软件部署到docker镜像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?


2921
2018-04-16 21:19


起源


Docker与KVM性能分析: bodenr.blogspot.com/2014/05/... - HDave
如果你正在寻找他们的图像之间的差异 - stackoverflow.com/questions/29096967/... - devesh-ahuja
Docker不是虚拟机 - 它是一种配置管理工具。 - aaa90210
@JagatveerSingh以为我会提到这是回到同一个问题的链接。 - Dan Nissenbaum
Stack Overflow是一个编程和开发问题的站点。这个问题似乎是偏离主题的,因为它不是关于编程或开发。看到 我在这里可以问什么主题 在帮助中心。也许 超级用户 要么 Unix和Linux堆栈交换 会是一个更好的地方。 - jww


答案:


Docker最初使用的 LinuX容器 (LXC),但后来转为 runC (原名 libcontainer),它在与其主机相同的操作系统中运行。这允许它共享许多主机操作系统资源。此外,它使用分层文件系统(AUFS)并管理网络。

AuFS是一个分层文件系统,因此您可以将只读部分和写入部分合并在一起。可以将操作系统的公共部分设置为只读(并在所有容器之间共享),然后为每个容器提供自己的挂载以进行写入。

所以,假设你有一个1 GB的容器图像;如果您想使用完整的VM,则需要1 GB x倍的VM数量。使用Docker和AuFS,您可以在所有容器之间共享1 GB的大部分,如果您有1000个容器,您仍然可能只有1 GB以上的空间用于容器OS(假设它们都运行相同的OS映像) 。

完整的虚拟化系统可以获得分配给它的自己的资源集,并实现最小的共享。你得到更多隔离,但它更重(需要更多资源)。使用Docker可以减少隔离,但容器很轻(需要的资源更少)。因此,您可以在主机上轻松运行数千个容器,甚至不会闪烁。尝试使用Xen,除非你有一个非常大的主机,我认为这是不可能的。

完整的虚拟化系统通常需要几分钟才能启动,而Docker / LXC / runC容器需要几秒钟,通常甚至不到一秒钟。

每种类型的虚拟化系统都有利弊。如果您希望使用有保证的资源进行完全隔离,则可以使用完整的VM。如果您只想将进程彼此隔离并希望在合理大小的主机上运行大量进程,那么Doc​​ker / LXC / runC似乎就是您的选择。

有关更多信息,请查看 这组博客文章 它很好地解释了LXC的工作原理。

为什么将软件部署到docker镜像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?

部署一致的生产环境说起来容易做起来难。即使你使用像这样的工具 厨师 和 木偶,总是有操作系统更新和其他在主机和环境之间发生变化的事情。

Docker使您能够将操作系统快照到共享映像中,并使其易于部署在其他Docker主机上。本地,dev,qa,prod等:所有相同的图像。当然,你可以使用其他工具,但不是那么容易或快速。

这非常适合测试;假设您有数千个需要连接到数据库的测试,每个测试都需要数据库的原始副本,并且会对数据进行更改。对此的经典方法是在每次测试后使用自定义代码或使用类似工具重置数据库 迁飞  - 这可能非常耗时,并且意味着测试必须连续运行。但是,使用Docker,您可以创建数据库的映像并在每个测试中运行一个实例,然后并行运行所有测试,因为您知道它们都将针对数据库的同一快照运行。由于测试是并行运行的,并且在Docker容器中,它们可以同时在同一个盒子上运行,并且应该更快地完成。尝试使用完整的VM。

来自评论......

有趣!我想我仍然对“快照[操作系统”的概念感到困惑。如果没有,那么,如何制作操作系统的图像?

好吧,让我们看看我是否可以解释。您从基础映像开始,然后进行更改,并使用docker提交这些更改,并创建一个映像。此图像仅包含与基础的差异。当您想要运行图像时,您还需要基础,并使用分层文件系统将图像分层在基础之上:如上所述,Docker使用AUFS。 AUFS将不同的层合并在一起,就可以得到你想要的东西;你只需要运行它。您可以继续添加越来越多的图像(图层),它将继续只保存差异。因为Docker通常建立在现成的图像之上 注册处,你很少需要自己“快照”整个操作系统。


2817
2018-04-16 22:35



Ken,在某些地方你将操作系统与内核混为一谈。主机上的所有容器都在同一个内核下运行,但其余的OS文件对于每个容器都是唯一的。 - Andy
有趣!我想我仍然对“快照[操作系统”的概念感到困惑。如果没有,那么,如何制作操作系统的图像? - zslayton
@ murtaza52他们正在添加对不同文件系统的支持,因此Aufs消失应该不是问题。不确定何时会添加32位支持,不要认为有强烈的需求,因此优先级列表很低,但我可能错了。 - Ken Cochrane
@Mike:......无疑是受到了启发 FreeBSD监狱  HISTORY The jail utility appeared in FreeBSD 4.0. - Stefan Paletta
对于那些想知道我们正在回复的@ Mike's评论的人,因为它似乎被删除了,它是这样的:<缺少的一件事是提到Linux容器是真正的灵感源的克隆这一事实:Solaris Containers。早在2004年......这是一个革命性的概念,是一个伟大的,伟大的方式来做真正高效的经济实惠的托管虚拟机。 Joyent是我第一个意识到的......> - Jeffrey 'jf' Lim


好的答案。只是为了得到容器与VM的图像表示,请看下面的一个。

enter image description here

资源: https://www.docker.com/what-c​​ontainer#/package_software


342
2017-10-14 18:02



<strike>据我所知,在“docker引擎”之上应该有一个共享的linux内核。然后通常甚至共享bin / libs。之后是第一个特定于每个容器的bin / libs和apps。如果我错了,请纠正我。</ strike>我错了。 Docker镜像与主机共享内核,请参阅 superuser.com/questions/889472/...。但是,为了说明容器的union文件系统,可能在docker引擎的正上方有一个共享的libs / bin层。 - Betamos
我上面的图片有问题,因为Hypervisor可以安装在裸机/基础设施上,但Docket不能(还) - reza
@reza,我同意Hypervisor可以安装在Bare metal上,但重点是Docker建议用于应用程序的容器化以及如何限制或避免某些情况下不需要/适用的虚拟化。 Ken Cochrane对此进行了更详细的解释 stackoverflow.com/a/16048358/2478933 - manu97
这并没有说明是什么 Docker引擎。非常抽象的图片。 - kyb
容器和内核之间没有“Docker Engine”层,容器只是内核中特殊设置的进程(名称空间,cgroups等) - Paweł Prażak


了解虚拟化和容器如何在低级别工作可能会有所帮助。这将清除很多事情。

注意:我在下面的描述中简化了一点。有关更多信息,请参阅参考

虚拟化如何在低级别工作?

在这种情况下,VM管理器接管CPU环0(或较新CPU中的“根模式”)并拦截客户操作系统发出的所有特权调用,以创建客户操作系统具有自己的硬件的错觉。有趣的事实:在1998年之前,人们认为在x86架构中无法实现这一点,因为没有办法进行这种拦截。 VMWare的人 是第一个 谁有想法重写内存中的可执行字节以实现客户操作系统的特权调用。

实际效果是虚拟化允许您在相同的硬件上运行两个完全不同的操作系统。每个客户操作系统都经历了引导,加载内核等所有过程。您可以拥有非常严格的安全性,例如,客户操作系统无法完全访问主机操作系统或其他客户端并搞砸了。

容器如何在低水平工作?

周围 2006年人们包括谷歌的一些员工实施了新的内核级别功能 命名空间 (不过这个想法  之前 存在于FreeBSD中)。操作系统的一个功能是允许将全局资源(如网络和磁盘)共享到进程。如果将这些全局资源包装在命名空间中,以使它们仅对在同一命名空间中运行的那些进程可见,该怎么办?比如说,你可以获得一大块磁盘并将其放在命名空间X中,然后在命名空间Y中运行的进程无法查看或访问它。类似地,名称空间X中的进程无法访问分配给名称空间Y的内存中的任何内容。当然,X中的进程无法查看或与名称空间Y中的进程通信。这为全局资源提供了一种虚拟化和隔离。这就是docker的工作原理:每个容器都在自己的命名空间中运行,但完全使用 相同 内核作为所有其他容器。发生隔离是因为内核知道分配给进程的命名空间,并且在API调用期间确保进程只能访问其自己的命名空间中的资源。

容器与VM的限制现在应该是显而易见的:您不能在VM中的容器中运行完全不同的操作系统。不过你 能够 运行Linux的不同发行版,因为它们共享相同的内核。隔离级别不如VM中那么强。实际上,“guest”容器有一种方法可以在早期实现中接管主机。您还可以看到,当您加载新容器时,操作系统的整个新副本不会像在VM中那样启动。所有容器 共享相同的内核。这就是容器重量轻的原因。与VM不同,您不必为容器预先分配大量内存,因为我们没有运行新的OS副本。这样就可以在一个操作系统上运行数千个容器,同时对它们进行沙盒处理,如果我们在自己的虚拟机中运行单独的操作系统副本,这可能是不可能的。


298
2018-01-13 01:49



哇,感谢伟大的低级解释(和历史事实)。我正在寻找那个,而不是上面找到的。你是什​​么意思 “你可以运行不同的Linux发行版,因为它们共享同一个内核。”?您是说客户容器必须具有完全相同的Linux内核版本,或者它无关紧要?如果我在guest虚拟机上调用OS命令但仅在guest虚拟机内核中支持并不重要。或者例如在客户内核中修复但在主机内核中没有修复的错误。所有客人都会表现出错误,对吗?即使客人打了补丁。 - Jeach
@Jeach:容器没有自己的内核,它们共享/使用主机之一。因此,您无法在同一台计算机/ VM上运行需要不同内核的容器。 - user276648
问:你写道,谷歌的一些员工在1996年左右参与了名称空间内核功能 - 但谷歌直到1998年才成立。你的意思是'后来成为谷歌员工的人'吗? - Martin Gjaldbaek
@martin - 感谢您注意到2006年。此外,我应该提到自2002年以来Linux中存在不同类型的命名空间,但2006年的工作是容器化的基础。我已经参考更新了答案。 - ShitalShah
+1这应该是明确的答案,而其他答案提供一些澄清,只有自下而上的低级别解释可以清除这种技术如何工作,'过程分组在他们自己的名称空间=容器'。非常感谢你,我现在明白了。 - Tino Mclaren


我喜欢Ken Cochrane的回答。

但是我想添加额外的观点,这里没有详细介绍。在我看来,Docker在整个过程中也有所不同。与VM相比,Docker不是(仅)关于硬件的最佳资源共享,而且它为打包应用程序提供了一个“系统”(优先但不是必须的,作为一组微服务)。

对我而言,它适用于开发人员导向工具(如rpm,debian软件包,maven,npm + git)和Ops工具(如Puppet,VMWare,Xen)之间的差距,您可以将其命名为...

为什么将软件部署到docker镜像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?

您的问题假设一些一致的生产环境。 但如何保持一致?  考虑一些(> 10)服务器和应用程序,管道中的阶段。 为了保持同步,你将开始使用像Puppet,Chef或你自己的配置脚本,未发布的规则和/或大量文档......理论上服务器可以无限期运行,并保持完全一致和最新。实践无法完全管理服务器的配置,因此存在相当大的配置偏差范围,以及对运行的服务器的意外更改。

因此,有一种已知的模式可以避免这种情况,即所谓的模式 不可变服务器。但是不可变的服务器模式并不受欢迎。主要是因为VM的限制,它在Docker之前使用。处理几千兆字节的大图像,移动那些大图像,只是为了改变应用程序中的某些字段,非常非常费力。可以理解的......

使用Docker生态系统,您永远不需要在“小变化”(感谢aufs和Registry)上移动千兆字节,并且您不必担心通过在运行时将应用程序打包到Docker容器中而失去性能。您无需担心该图像的版本。 最后,即使在您的Linux笔记本电脑上,您甚至可以经常复制复杂的生产环境(如果您的情况不起作用,请不要打电话给我;))

当然,您可以在VM中启动docker容器(这是一个好主意)。减少VM级别的服务器配置。以上所有内容都可以由Docker管理。

附:同时Docker使用自己的实现“libcontainer”而不是LXC。但LXC仍然可用。


280
2017-09-19 16:21



在rpm和dpkg等一组工具中包含git似乎很奇怪。我之所以提到这一点是因为我看到尝试使用版本控制系统(如git)作为分发/打包工具会引起很多混乱。 - blitzen9872
但他并没有错,git可以用于包管理,例如bower在内部基本上是用于下载git标签的花哨cli。 - roo2
在容器中包装应用程序是一种有趣且有效的方法。但是,如果您将它打包在docker中,这将是过度的,因为不会直接支持依赖项或任何共享库。这正是Ubuntu Snap和Flatpak for Redhat等新包装技术正在努力实现的目标。在我看来,其中一种封装技术将赢得并成为Linux封装的未来。 - yosefrow


Docker不是虚拟化方法。它依赖于实际实现基于容器的虚拟化或操作系统级虚拟化的其他工具。为此,Docker最初使用LXC驱动程序,然后转移到libcontainer,现在重命名为runc。 Docker主要专注于在应用程序容器内自动部署应用程序。应用程序容器旨在打包和运行单个服务,而系统容器则设计为运行多个进程,如虚拟机。因此,Docker被视为容器化系统上的容器管理或应用程序部署工具。

为了了解它与其他虚拟化的不同之处,让我们来看看虚拟化及其类型。然后,更容易理解那里有什么不同。

虚拟化

在其构思形式中,它被认为是逻辑上划分大型机以允许多个应用程序同时运行的方法。但是,当公司和开源社区能够以某种方式提供处理特权指令的方法并允许在单个基于x86的系统上同时运行多个操作系统时,场景发生了巨大变化。

管理程序

管理程序处理创建客户虚拟机操作的虚拟环境。它监督客户系统并确保在必要时为客户分配资源。虚拟机管理程序位于物理机和虚拟机之间,并为虚拟机提供虚拟化服务。为了实现它,它拦截虚拟机上的客户操作系统操作并模拟主机操作系统上的操作。

虚拟化技术的快速发展,主要是在云中,通过允许在虚拟机管理程序(如Xen,VMware Player,KVM等)的帮助下在单个物理服务器上创建多个虚拟服务器,进一步推动了虚拟化的使用。在商用处理器中加入硬件支持,例如Intel VT和AMD-V。

虚拟化的类型

可以基于虚拟化方法如何模仿客户操作系统的硬件并模拟客户操作环境来对虚拟化方法进行分类。主要有三种类型的虚拟化:

  • 仿真
  • 半虚拟化
  • 基于容器的虚拟化

仿真

仿真,也称为完全虚拟化,完全在软件中运行虚拟机操作系统内核。此类型中使用的管理程序称为Type 2管理程序。它安装在主机操作系统的顶部,负责将客户操作系统内核代码转换为软件指令。翻译完全由软件完成,无需硬件参与。仿真使得可以运行支持所模拟环境的任何未修改的操作系统。此类虚拟化的缺点是额外的系统资源开销导致与其他类型的虚拟化相比性能下降。

Emulation

此类别中的示例包括VMware Player,VirtualBox,QEMU,Bochs,Parallels等。

半虚拟化

半虚拟化,也称为Type 1虚拟机管理程序,直接在硬件上运行,或“裸机”,并直接向运行在其上的虚拟机提供虚拟化服务。它可以帮助操作系统,虚拟化硬件和真实硬件协作以实现最佳性能。这些管理程序通常具有相当小的占用空间,并且本身不需要大量资源。

此类别中的示例包括Xen,KVM等。

Paravirtualization

基于容器的虚拟化

基于容器的虚拟化(也称为操作系统级虚拟化)可在单个操作系统内核中实现多个独立执行。它具有最佳的性能和密度,并具有动态资源管理功能。此类虚拟化提供的隔离虚拟执行环境称为容器,可以视为一组跟踪的进程。

Container-based virtualization

通过添加到Linux内核版本2.6.24的名称空间功能,可以实现容器的概念。容器将其ID添加到每个进程,并向每个系统调用添加新的访问控制检查。它是由访问 克隆() 系统调用,允许创建以前全局命名空间的单独实例。

命名空间可以以多种不同的方式使用,但最常见的方法是创建一个隔离的容器,该容器对容器外的对象没有可见性或访问权限。在容器内运行的进程似乎在普通的Linux系统上运行,尽管它们与位于其他命名空间中的进程共享底层内核,对于其他类型的对象也是如此。例如,在使用名称空间时,容器内的root用户不会被视为容器外的root用户,从而增加了额外的安全性。

Linux控制组(cgroups)子系统是启用基于容器的虚拟化的下一个主要组件,用于对进程进行分组并管理其聚合资源消耗。它通常用于限制容器的内存和CPU消耗。由于容器化的Linux系统只有一个内核,并且内核对容器具有完全可见性,因此只有一个级别的资源分配和调度。

Linux容器有多种管理工具,包括LXC,LXD,systemd-nspawn,lmctfy,Warden,Linux-VServer,OpenVZ,Docker等。

容器与虚拟机

与虚拟机不同,容器不需要引导操作系统内核,因此可以在不到一秒的时间内创建容器。此功能使基于容器的虚拟化比其他虚拟化方法更加独特和可取。

由于基于容器的虚拟化为主机增加了很少或没有开销,因此基于容器的虚拟化具有接近本机的性能

对于基于容器的虚拟化,与其他虚拟化不同,不需要其他软件。

主机上的所有容器共享主机的调度程序,从而节省了额外资源的需求。

与虚拟机映像相比,容器状态(Docker或LXC映像)的大小很小,因此容器映像很容易分发。

容器中的资源管理是通过cgroup实现的。 Cgroups不允许容器消耗比分配给它们更多的资源。但是,截至目前,主机的所有资源都在虚拟机中可见,但无法使用。这可以通过运行来实现 top 要么 htop 在容器和主机上同时进行。所有环境的输出看起来都很相似。


124
2018-04-02 00:55



非常好的答案。请问,你从哪里得到这些图表?原文/书,即。 - Harry
我使用Google绘图创建了这些图表。我的Google图纸帐户中仍然有这些。 - Ashish Bista
和文字?这个答案的原文来源是什么? - L0j1k
@Sheljohn这个答案的第一个版本是从另一个来源逐字复制而没有归属。 - L0j1k
@AshishBista如果要使用从其他地方逐字逐句采集的文本,则需要对源进行属性/链接。 - L0j1k


通过这篇文章,我们将在VM和LXC之间划出一些差异。我们先来定义它们。

VM

虚拟机模拟物理计算环境,但是对CPU,内存,硬盘,网络和其他硬件资源的请求由虚拟化层管理,该虚拟化层将这些请求转换为底层物理硬件。

在此上下文中,VM被称为Guest,而其运行的环境称为主机。

LXCS:

Linux Containers(LXC)是操作系统级功能,可以在一个控制主机(LXC主机)上运行多个独立的Linux容器。 Linux Containers是虚拟机的轻量级替代品,因为它们不需要虚拟机管理程序即可。 Virtualbox,KVM,Xen等

现在,除非你被艾伦(Zach Galifianakis-来自宿醉系列)吸毒并且去年一直在拉斯维加斯,你会非常清楚Linux容器技术的巨大兴趣,如果我将特定的一个容器最近几个月在全球引起轰动的项目是 - Docker引发了一些人们对云计算环境应该放弃虚拟机(VM)的看法,并且由于其较低的开销和可能更好的性能而将其替换为容器。

但最重要的问题是,它是可行的吗?它会是明智的吗?

一个。 LXC的范围限定为Linux的一个实例。它可能是Linux的不同风格(例如,CentOS主机上的Ubuntu容器,但它仍然是Linux。)同样,如果我们查看具有相当广泛范围的VM并使用它,则基于Windows的容器现在限定为Windows实例。虚拟机管理程序您不仅限于操作系统Linux或Windows。

湾与VM相比,LXC具有低开销并且具有更好的性能。工具即。构建在LXC技术肩上的Docker为开发人员提供了运行其应用程序的平台,同时为操作人员提供了一个工具,使他们能够在生产服务器或数据中心部署相同的容器。它试图在运行应用程序的开发人员,启动和测试应用程序以及无缝部署该应用程序的操作人员之间进行体验,因为这是所有摩擦所在的地方,DevOps的目的是打破这些孤岛。

因此,最好的方法是云基础架构提供商应该提倡适当使用VM和LXC,因为它们都适合处理特定的工作负载和方案。

放弃虚拟机目前尚不实用。因此,VM和LXC都有自己的个体存在和重要性。


118
2017-08-26 07:46



上面的部分“b”正是Docker人员对该技术所说的话。这是为了进行开发 和 部署任务更容易。根据我作为开发人员和系统管理员的经验,我必须同意。 - WineSoaked
这是非常抽象的答案。我们需要用例何时使用/不使用Docker。这就是问题所在。每个人都可以找到Docker的样子,但只有少数人可以解释真实场景。 - Ivan Voroshilin
你能澄清一下“a”部分吗?语言不是很清楚。 - aamir
docker现在被带入windows世界,因为它不再依赖于LXC: blogs.msdn.com/b/nzdev/archive/2015/06/02/... 如果我在这里误解了答案,请纠正我 - bubakazouba
我很难理解 “(例如,Centos主机上的Ubuntu容器,但它仍然是Linux)” 部分容器。我理解它的方式是容器共享主机内核。例如,如果我有一台运行Linux内核4.6的主机虚拟机,则有多个客户虚拟机运行Linux内核2.4,2.6,3.2,4.1和4.4。如果我执行特定于该内核的命令,我将获得客户内核的行为(而不是主机)。但是如果我的guest虚拟机VM现在是容器,那么执行的命令是由主机内核决定的吗? - Jeach


这里的大部分答案都是关于虚拟机的。我将在过去几年中使用Docker这个问题给你一个单行回复。就是这样:

Docker只是运行进程的一种奇特方式,而不是虚拟机。

现在,让我解释一下这意味着什么。虚拟机是他们自己的野兽。我想解释一下 搬运工人 除了解释虚拟机是什么之外,它将帮助您理解这一点。特别是因为这里有很多很好的答案,告诉你当他们说“虚拟机器”时他们究竟是什么意思。所以...

Docker容器只是一个使用分区的进程(及其子进程) 的cgroup 来自其余进程的主机系统内核。您可以通过运行实际查看Docker容器进程 ps aux 在主持人。例如,开始 apache2 “在容器中”刚刚开始 apache2 作为主持人的特殊过程。它刚刚与机器上的其他进程分开。重要的是要注意,您的容器在容器化过程的生命周期之外不存在。当您的过程死亡时,您的容器会死亡。那是因为Docker取代了 pid 1 在您的容器内与您的应用程序(pid 1 通常是init系统)。关于这一点 pid 1 非常重要。

至于每个容器进程使用的文件系统,Docker使用 的unionfs备份图像,这是你在做的时候下载的 docker pull ubuntu。每个“图像”只是一系列图层和相关元数据。分层的概念在这里非常重要。每个图层只是从它下面的图层的变化。例如,当您在构建Docker容器时删除Dockerfile中的文件时,实际上只是在最后一层上创建了一个图层,上面写着“此文件已被删除”。顺便说一句,这就是您可以从文件系统中删除大文件的原因,但图像仍占用相同数量的磁盘空间。该文件仍然存在于当前文件下面的图层中。图层本身只是文件的tarball。你可以测试一下 docker save --output /tmp/ubuntu.tar ubuntu接着 cd /tmp && tar xvf ubuntu.tar。然后你可以看看周围。所有看起来像长哈希的目录实际上都是单独的层。每个包含文件(layer.tar)和元数据(json)有关于该特定层的信息。这些层只描述了对文件系统的更改,这些更改被保存为“在其原始状态之上”的层。在读取“当前”数据时,文件系统读取数据,就好像它只查看最顶层的更改一样。这就是为什么文件似乎被删除,即使它仍然存在于“之前”的图层中,因为文件系统只查看最顶层。这允许完全不同的容器共享其文件系统层,即使每个容器中最顶层的文件系统可能发生了一些重大更改。当容器共享基础图像层时,这可以为您节省大量磁盘空间。但是,当您通过卷将主机系统中的目录和文件装入容器时,这些卷会“绕过”UnionFS,因此更改不会存储在层中。

Docker中的网络是通过使用以太网桥实现的(称为 docker0 在主机上),以及主机上每个容器的虚拟接口。它创建了一个虚拟子网 docker0 让你的容器彼此之间“沟通”。这里有许多网络选项,包括为容器创建自定义子网,以及“共享”主机网络堆栈以便容器直接访问的功能。

Docker移动速度非常快。它的 文件 是我见过的一些最好的文档。它通常写得很好,简洁,准确。我建议您查看可用的文档以获取更多信息,并相信您在线阅读的任何文档,包括Stack Overflow。如果您有具体问题,我强烈建议加入 #docker 在Freenode IRC并询问(你甚至可以使用Freenode的 网上聊天 为了那个原因!)。


91
2018-04-04 02:35



“Docker只是运行流程的一种奇特方式,而不是虚拟机。”这是一个很棒的总结,谢谢! - mkorman
谢谢!这个功能归功于programmerq #dockerFreenode IRC上的频道。 - L0j1k
这是一个很好的答案。我喜欢这个比喻。 - Teoman shipahi