Docker与虚拟机有何不同?
我一直在重读Docker文档,试图了解Docker和完整VM之间的区别.它如何设法提供完整的文件系统,隔离的网络环境等,而不是那么重?
为什么将软件部署到Docker映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
回答
Docker最初使用LinuX容器(LXC),但后来切换到runC(以前称为libcontainer),它运行在与其主机相同的操作系统中.这允许它共享许多主机操作系统资源.此外,它使用分层文件系统(AuFS)并管理网络.
AuFS是一个分层文件系统,因此您可以将只读部分和写入部分合并在一起.可以将操作系统的公共部分设置为只读(并在所有容器之间共享),然后为每个容器提供自己的写入挂载.
所以,假设你有一个1 GB的容器图像; 如果您想使用完整的VM,则需要1 GB x倍的VM数量.使用Docker和AuFS,您可以在所有容器之间共享1 GB的大部分,如果您有1000个容器,您仍然可能只有超过1 GB的容器OS空间(假设它们都运行相同的操作系统映像) .
完整的虚拟化系统获得分配给它的自己的一组资源,并进行最小的共享.你得到更多隔离,但它更重(需要更多资源).使用Docker可以减少隔离,但容器很轻(需要的资源更少).因此,您可以轻松地在主机上运行数千个容器,甚至不会闪烁.尝试使用Xen,除非你有一个非常大的主机,我认为这是不可能的.
完整的虚拟化系统通常需要几分钟才能启动,而Docker/LXC/runC容器需要几秒钟,通常甚至不到一秒钟.
每种类型的虚拟化系统都有利弊.如果您希望使用有保证的资源进行完全隔离,则可以使用完整的VM.如果您只想将进程彼此隔离并希望在合理大小的主机上运行大量进程,那么Docker/LXC/runC似乎就是您的选择.
有关更多信息,请查看这组博客文章,这些文章很好地解释了LXC的工作原理.
部署一致的生产环境说起来容易做起来难.即使您使用Chef和Puppet等工具,也总会有操作系统更新以及主机和环境之间发生变化的其他事情.
Docker使您能够将操作系统快照到共享映像中,并且可以轻松地在其他Docker主机上进行部署.本地,dev,qa,prod等:所有相同的图像.当然,你可以使用其他工具,但不是那么容易或快速.
这非常适合测试; 假设您有数千个需要连接到数据库的测试,每个测试都需要数据库的原始副本,并且会对数据进行更改.经典的方法是在每次测试后使用自定义代码或使用Flyway等工具重置数据库- 这可能非常耗时,并且意味着测试必须连续运行.但是,使用Docker,您可以创建数据库的映像并在每个测试中运行一个实例,然后并行运行所有测试,因为您知道它们都将针对数据库的同一快照运行.由于测试是并行运行的,并且在Docker容器中,它们可以同时在同一个盒子上运行,并且应该更快地完成.尝试使用完整的VM.
来自评论......
那么,让我们看看我是否可以解释.您从基本映像开始,然后进行更改,并使用docker提交这些更改,并创建一个映像.此图像仅包含与基础的差异.当您想要运行图像时,您还需要基础,并使用分层文件系统将图像分层在基础之上:如上所述,Docker使用AUFS.AUFS将不同的层合并在一起,就可以得到你想要的东西; 你只需要运行它.您可以继续添加越来越多的图像(图层),它将继续只保存差异.由于Docker通常构建在注册表中的现成映像之上,因此您很少需要自己"快照"整个操作系统.
- Ken,在某些地方你将操作系统与内核混为一谈.主机上的所有容器都在同一个内核下运行,但其余的OS文件在每个容器中都是唯一的.
- 有趣!我想我仍然对"快照[操作系统"的概念感到困惑.如果没有,那么,如何制作操作系统的图像?
- @Mike:......无疑是受[FreeBSD jails]启发的(https://en.wikipedia.org/wiki/FreeBSD_jail)`历史.Jail实用程序出现在FreeBSD 4.0中.
- 对于那些想知道我们正在回复的@ Mike's评论的人,因为它似乎被删除了,它是这样的:<缺少的一件事是提到Linux容器是真正灵感来源的克隆这一事实:Solaris Containers.早在2004年......这是一个革命性的概念,是一个伟大的,伟大的方式来做真正高效的经济实惠的托管虚拟机.Joyent是第一个我意识到的......>
- @ murtaza52他们正在添加对不同文件系统的支持,因此Aufs消失应该不是问题.不确定何时会添加32位支持,不要认为有强烈的需求,所以优先级列表很低,但我可能错了.
- 为了澄清,操作系统"userland"是磁盘上的一堆文件.内核是可以在磁盘或ROM中的部分,或者由LXC传递到容器,并首先运行这些文件.它也是Linux发行版之间变化不大的部分.因为lxc可以使用任何图像(思考文件夹)作为新用户区的根,所以你可以拥有m个发行版的n个共享实例,所有这些实例都是独立运行的,但每个实例都写入磁盘上自己的非共享位置.但是,您也可以随时对这些实例中的任何实例进行快照,并将其用作其他实例的新共享起点.
- 还有一部分我还是不明白.假设我正在使用ubuntu在笔记本电脑上工作,我用docker拉出centos图像.当我运行docker时,如何在CentOS环境中完全运行某些东西,同时仍然停留在Ubuntu而不使用虚拟化?它仍然会使用我的Ubuntu内核?
- @Andrea:我打赌是的,但只是内核
- @DenisWeerasiri如果你为每个容器运行一个测试,然后更正,其他测试都看不到对该容器的任何更改.通常,对于数据库容器,将持久性数据存储在容器外部的卷装入中.当您希望每次都重用相同的数据库映像时,这对于生产使用很有用,但不适用于测试.
- 从开发人员的角度来看,@ Ajedi32是一个工具,可以很容易地使用纯文本文件将运行时环境置于版本控制**之下.
- 你不能在 Linux 上运行 Windows 容器,因为 Windows 内核不是开源的。但是你可以在 Windows 上运行 Linux 容器。有关更多详细信息,请参阅 Microsoft 的这篇博文:https://blogs.technet.microsoft.com/hybridcloud/2017/04/18/dockercon-2017-powering-new-linux-innovations-with-hyper-v-isolation-和-windows-server/ 正因为如此,你可以在带有 Linux 容器的 windows 上开发,也可以在任何 Linux 服务器上运行它,这样你就可以真正构建一次,随处运行。
- @Ken - 鉴于未来的ubuntu版本不支持aufs,docker.io是个不错的选择吗?http://askubuntu.com/questions/279127/doesnt-raring-mainline-kernelppa-v-3-8-3-support-aufs.另外我想让它在ubuntu 13.04(32位)上工作,我能做到这一点吗?
- @KenCochrane在单元测试场景中,我没有得到"他们将全部针对数据库的相同快照运行"的含义.这是否意味着,如果单元测试修改了数据库中的某些数据,其他单元测试仍然没有看到这些修改?如果是,那么Docker容器不能将持久存储作为服务公开,对吧?
- 我今天在其他地方发布了这个,但是对于有兴趣回答一些问题的人,James Turnbull已经写了(并且不断更新)Docker Book:dockerbook.com.这是很多当前和即将推出的功能和独特功能的绝佳参考.
- @ Ajedi32我没有使用过Chef或Puppet,但从这个意义上讲:是的.当然,Docker还有更多功能,但是对于完整的运行时环境而言,易于版本控制的明文配方是我作为开发人员的一个最重要的特性.
- `如果你想使用一个完整的虚拟机,你需要1GB倍x你想要的虚拟机数量. - 如果你使用VMWare,它已经支持了COW快照并且分叉了很多年......
- 虽然这是一个很好的答案,但它过分关注差异文件系统AuFS.这有点误导,因为虚拟机管理程序(例如VirtualBox)通常几乎就具有此功能,其名称类似于"快照"或"差异磁盘".甚至使用Dockerfile构建映像的便利性原则上也可以使用虚拟机完成(但实际上Docker非常好).更好地关注性能,例如流程调度.
- 我将在上面的优秀答案中添加的一件事是,虽然docker允许您分离二进制文件和库并且您的环境受到很大程度的控制,但是docker无法控制内核.如果您的应用程序需要在内核中设置某些功能(例如禁用MongoDB似乎需要的"transparent_hugepage"),那么您无法在docker镜像中真正隔离它.但是,维护一致的内核设置比维护整个一致的部署环境(容器,库,配置文件等)要容易得多.
- 听起来,它与Windows终端服务器仅保存公共服务器上运行的每个用户的基本操作系统的增量的方式密切相关,略有不同的是,他们不仅要对文件进行增量处理,还要对可怕的注册表进行增量处理.想知道谁首先做了Citrix或Sun,还是更老的概念呢?
- 可以很好地包含一些参考[Kubernetes](https://github.com/GoogleCloudPlatform/kubernetes).谷歌上周解放了它.
- _如果您想使用完整虚拟机,则需要1GB倍x所需的虚拟机数量.虽然某些虚拟机系统(如带有Netapp的VMware)具有技巧(精简配置,压缩,重复数据删除),但可以大大减少数量需要存储空间.
- 那么从app开发者的角度来看,Docker只是一个性能更好的VM?
- 分层文件系统是仅在构建映像时还是在运行容器时发生的?所以,如果我用ubuntu操作系统运行两个容器,而ubuntu操作系统需要1G,那么运行容器需要1GB还是2GB?
- @jas如果容器图像是1GB,那么两者都是1GB,加上每个容器自己添加的任何额外空间.日志等
好的答案.只是为了得到容器与VM的图像表示,请看下面的那个.
资源
- <strike>据我所知,在"docker引擎"之上应该有一个共享的linux内核.然后通常甚至共享bin/libs.之后是第一个特定于每个容器的bin/libs和apps.如果我错了,请纠正我.</ strike>我错了.Docker镜像与主机共享内核,请参阅http://superuser.com/questions/889472/docker-containers-have-their-own-kernel-or-not.但是,为了说明容器的union文件系统,可能在docker引擎的正上方有一个共享的libs/bin层.
- 我上面的图片有问题,因为Hypervisor可以安装在裸机/基础设施上,但Docket不能(还)
- 容器和内核之间没有"Docker Engine"层,容器只是内核中特殊设置的进程(名称空间,cgroups等)
- 这并没有说明什么是*Docker Engine*.非常抽象的图片.
了解虚拟化和容器如何在低级别工作可能会有所帮助.这将清除很多事情.
注意:我在下面的描述中简化了一点.有关更多信息,请参阅参考
虚拟化如何在低级别工作?
在这种情况下,VM管理器接管CPU环0(或较新CPU中的"根模式")并拦截来宾操作系统所做的所有特权调用,以创建客户操作系统具有自己的硬件的错觉.有趣的事实:在1998年之前,人们认为在x86架构中无法实现这一点,因为没有办法进行这种拦截.VMWare的人员是第一个有想法在内存中重写可执行字节以实现客户操作系统的特权调用的人.
实际效果是虚拟化允许您在同一硬件上运行两个完全不同的操作系统.每个客户操作系统经过引导的所有过程,加载内核等.您可以有很严格的安全性,例如,来宾操作系统不能得到充分地访问主机操作系统或其他客人,并把事情搞得一团糟.
容器如何在低水平工作?
大约2006年,人们包括一些谷歌员工实施了新的内核级别的功能,称为命名空间(不过这个想法长之前在FreeBSD的存在).操作系统的一个功能是允许将全局资源(如网络和磁盘)共享到进程.如果将这些全局资源包装在名称空间中,以使它们仅对在同一名称空间中运行的那些进程可见,该怎么办?比如说,你可以获得一大块磁盘并将其放在命名空间X中,然后在命名空间Y中运行的进程无法查看或访问它.类似地,名称空间X中的进程无法访问分配给名称空间Y的内存中的任何内容.当然,X中的进程无法查看或与名称空间Y中的进程通信.这为全局资源提供了一种虚拟化和隔离.这是码头工人是如何工作的:每个容器在其自己的命名空间中运行,但使用完全一样的内核,因为所有其他容器.发生隔离是因为内核知道分配给进程的命名空间,并且在API调用期间确保进程只能访问其自己的命名空间中的资源.
容器与VM的限制现在应该是显而易见的:您不能在VM中的容器中运行完全不同的操作系统.但是,您可以运行不同的Linux发行版,因为它们共享相同的内核.隔离级别不如VM中那么强.实际上,"guest"容器有一种方法可以在早期实现中接管主机.您还可以看到,当您加载新容器时,操作系统的整个新副本不会像在VM中那样启动.所有容器共享相同的内核.这就是容器重量轻的原因.与VM不同,您不必为容器预先分配大量内存,因为我们没有运行新的操作系统副本.这样就可以在一个操作系统上运行数千个容器,同时对它们进行沙盒处理,如果我们在自己的VM中运行单独的操作系统副本,这可能是不可能的.
- 哇,感谢伟大的低级解释(和历史事实).我正在寻找那个,而不是上面找到的.你是什么意思_"你可以运行不同的Linux发行版,因为它们共享相同的内核."_?您是说客户容器必须具有完全相同的Linux内核版本,或者它无关紧要?如果我在guest虚拟机上调用OS命令但仅在guest虚拟机内核中支持并不重要.或者例如在客户内核中修复但在主机内核中没有修复的错误.所有客人都会表现出错误,对吗?即使客人打了补丁.
- +1这应该是明确的答案,而其他答案提供一些澄清,只有自下而上的低级别解释可以清除这种技术如何工作,'流程分组在他们自己的名称空间=容器'.非常感谢你,我现在明白了.
- @Jeach:容器没有自己的内核,它们共享/使用主机之一.因此,您无法在同一台计算机/ VM上运行需要不同内核的容器.
- @martin - 感谢您注意到2006年.此外,我应该提到自2002年以来Linux中存在不同类型的命名空间,但2006年的工作是容器化的基础.我已经参考更新了答案.
- 问:你写道,谷歌的一些员工在1996年左右参与了名称空间内核功能 - 但谷歌直到1998年才成立.你的意思是'后来成为谷歌员工的人'吗?
- 是。但是请注意,容器不仅仅是名称空间的应用程序。它还使用控制组等工具进行资源限制和计费,并使用具有联合能力的文件系统进行有效的文件系统分配。但是,是的,最终,容器是一堆预先存在的OS设施的用例。
我喜欢Ken Cochrane的回答.
但是我想添加额外的观点,这里没有详细介绍.在我看来,Docker在整个过程中也有所不同.与VM相比,Docker不(仅)关于硬件的最佳资源共享,而且它为打包应用程序提供了一个"系统"(最好,但不是必须的,作为一组微服务).
对我而言,它适用于面向开发人员的工具(如rpm,Debian软件包,Maven,npm + Git)和ops工具(如Puppet,VMware,Xen)之间的差距,您可以将其命名为......
您的问题假设一些一致的生产环境.但如何保持一致?
考虑一些(> 10)服务器和应用程序,管道中的阶段.
为了保持同步,你将开始使用像Puppet,Chef或你自己的配置脚本,未发布的规则和/或大量文档......理论上服务器可以无限期运行,并保持完全一致和最新.实践无法完全管理服务器的配置,因此配置偏差和运行服务器的意外更改存在相当大的余地.
因此,有一种已知的模式可以避免这种情况,即所谓的不可变服务器.但是不可变的服务器模式并不受欢迎.主要是因为Docker之前使用的VM的局限性.处理几千兆字节的大图像,移动那些大图像,只是为了改变应用程序中的某些字段,非常非常费力.可以理解的......
使用Docker生态系统,您永远不需要在"小变化"(感谢aufs和Registry)上移动千兆字节,并且您无需担心在运行时将应用程序打包到Docker容器中会导致性能下降.您无需担心该图像的版本.
最后,即使在您的Linux笔记本电脑上,您甚至经常能够重现复杂的生产环境(如果在您的情况下不起作用,请不要打电话给我;))
当然,您可以在VM中启动Docker容器(这是一个好主意).减少VM级别的服务器配置.以上所有内容都可以由Docker管理.
PS同时Docker使用自己的实现"libcontainer"而不是LXC.但LXC仍然可用.
- 但他并没有错,git可以用于包管理,例如bower在内部基本上是用于下载git标签的花哨cli.
- 将应用程序包装在容器中是一种有趣且有效的方法。但是,如果将其打包在docker中,这将是多余的,因为不会直接支持依赖项或任何共享库。这正是Ubuntu Snap和Flatpak for Redhat等新包装技术正在试图实现的目标。我认为,其中一种包装技术将获胜,并成为Linux中包装的未来。
Docker不是虚拟化方法.它依赖于实际实现基于容器的虚拟化或操作系统级虚拟化的其他工具.为此,Docker最初使用LXC驱动程序,然后转移到libcontainer,现在重命名为runc.Docker主要专注于自动化应用程序容器内的应用程序部署.应用程序容器旨在打包和运行单个服务,而系统容器则设计为运行多个进程,如虚拟机.因此,Docker被视为容器化系统上的容器管理或应用程序部署工具.
为了了解它与其他虚拟化的不同之处,让我们来看看虚拟化及其类型.然后,更容易理解那里有什么不同.
虚拟化
在其构思形式中,它被认为是逻辑上划分大型机以允许多个应用程序同时运行的方法.但是,当公司和开源社区能够以某种方式提供处理特权指令的方法并允许在单个基于x86的系统上同时运行多个操作系统时,场景发生了巨大变化.
管理程序
管理程序处理创建客户虚拟机操作的虚拟环境.它监督客户系统,并确保在必要时为客户分配资源.虚拟机管理程序位于物理机和虚拟机之间,并为虚拟机提供虚拟化服务.为了实现它,它拦截虚拟机上的客户操作系统操作并模拟主机操作系统上的操作.
虚拟化技术的快速发展(主要是在云中)通过允许在虚拟机管理程序(如Xen,VMware Player,KVM等)的帮助下在单个物理服务器上创建多个虚拟服务器,进一步推动了虚拟化的使用.在商用处理器中加入硬件支持,例如Intel VT和AMD-V.
虚拟化的类型
可以基于虚拟化方法如何模仿客户操作系统的硬件并模拟客户操作环境来对虚拟化方法进行分类.主要有三种类型的虚拟化:
- 仿真
- 半虚拟化
- 基于容器的虚拟化
仿真
仿真,也称为完全虚拟化,完全在软件中运行虚拟机操作系统内核.此类型中使用的管理程序称为Type 2管理程序.它安装在主机操作系统的顶部,负责将客户操作系统内核代码转换为软件指令.翻译完全由软件完成,无需硬件参与.仿真使得可以运行支持所模拟环境的任何未修改的操作系统.此类虚拟化的缺点是额外的系统资源开销导致与其他类型的虚拟化相比性能下降.
此类别中的示例包括VMware Player,VirtualBox,QEMU,Bochs,Parallels等.
半虚拟化
半虚拟化,也称为Type 1虚拟机管理程序,直接在硬件上运行,或"裸机",并直接向运行在其上的虚拟机提供虚拟化服务.它可以帮助操作系统,虚拟化硬件和真实硬件协作以实现最佳性能.这些管理程序通常具有相当小的占用空间,并且本身不需要大量资源.
此类别中的示例包括Xen,KVM等.
基于容器的虚拟化
基于容器的虚拟化(也称为操作系统级虚拟化)可在单个操作系统内核中实现多个独立执行.它具有最佳的性能和密度,并具有动态资源管理功能.这种类型的虚拟化提供的隔离虚拟执行环境称为容器,可以视为一组跟踪的进程.
通过添加到Linux内核版本2.6.24的名称空间功能,可以实现容器的概念.容器将其ID添加到每个进程,并向每个系统调用添加新的访问控制检查.它由clone()系统调用访问,该调用允许创建先前全局命名空间的单独实例.
命名空间可以以多种不同的方式使用,但最常见的方法是创建一个隔离的容器,该容器对容器外的对象没有可见性或访问权限.在容器内运行的进程似乎在普通的Linux系统上运行,尽管它们与位于其他命名空间中的进程共享底层内核,对于其他类型的对象也是如此.例如,在使用名称空间时,容器内的root用户不会被视为容器外的root用户,从而增加了额外的安全性.
Linux控制组(cgroups)子系统是启用基于容器的虚拟化的下一个主要组件,用于对进程进行分组并管理其聚合资源消耗.它通常用于限制容器的内存和CPU消耗.由于容器化Linux系统只有一个内核,并且内核对容器具有完全可见性,因此只有一个级别的资源分配和调度.
Linux容器有多种管理工具,包括LXC,LXD,systemd-nspawn,lmctfy,Warden,Linux-VServer,OpenVZ,Docker等.
容器与虚拟机
与虚拟机不同,容器不需要引导操作系统内核,因此可以在不到一秒的时间内创建容器.此功能使基于容器的虚拟化比其他虚拟化方法更加独特和可取.
由于基于容器的虚拟化为主机增加了很少或没有开销,因此基于容器的虚拟化具有接近本机的性能
对于基于容器的虚拟化,与其他虚拟化不同,不需要其他软件.
主机上的所有容器共享主机的调度程序,从而节省了额外资源的需求.
与虚拟机映像相比,容器状态(Docker或LXC映像)的大小很小,因此容器映像很容易分发.
容器中的资源管理是通过cgroup实现的.Cgroups不允许容器消耗比分配给它们更多的资源.但是,截至目前,主机的所有资源都在虚拟机中可见,但无法使用.这可以通过运行实现top
或htop
集装箱和主机在同一时间.所有环境的输出看起来都很相似.
更新:
Docker如何在非Linux系统中运行容器?
如果由于Linux内核中可用的功能而可以使用容器,那么显而易见的问题是非Linux系统如何运行容器.Docker for Mac和Windows都使用Linux VM来运行容器.Docker Toolbox用于在Virtual Box VM中运行容器.但是,最新的Docker在Windows中使用Hyper-V,在Mac中使用Hypervisor.framework.
现在,让我描述Docker for Mac如何详细运行容器.
Docker for Mac使用https://github.com/moby/hyperkit模拟管理程序功能,Hyperkit在其核心使用hypervisor.framework.Hypervisor.framework是Mac的本机管理程序解决方案.Hyperkit还分别使用VPNKit和DataKit来命名网络和文件系统.
Docker在Mac中运行的Linux VM是只读的.但是,你可以通过运行:
screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
.
现在,我们甚至可以检查此VM的内核版本:
# uname -a
.
Linux linuxkit-025000000001 4.9.93-linuxkit-aufs #1 SMP Wed Jun 6 16:86_64 Linux
所有容器都在此VM内运行.
hypervisor.framework有一些限制.因为Docker不会暴露docker0
Mac中的网络接口.因此,您无法从主机访问容器.截至目前,docker0
仅在VM内部可用.
Hyper-v是Windows中的本机管理程序.他们还试图利用Windows 10的功能本地运行Linux系统.
- 另请注意,您的工作正在复制到https://medium.com/@evalsocket/under-the-hood-docker-98f99189f38a,不予归因.
- @ L0j1k - 我会再说一遍:你的指责似乎是假的.你作为证据提供的文章都是在这个答案之后写的,它们似乎是在抄袭这个答案.这就是为什么你的评论被删除而你的旗帜没有被采取行动的原因.除非你能提供一个早于这个答案的来源,否则我建议你继续前进.
通过这篇文章,我们将在VM和LXC之间划出一些差异.我们先来定义它们.
VM:
虚拟机模拟物理计算环境,但是对CPU,内存,硬盘,网络和其他硬件资源的请求由虚拟化层管理,该虚拟化层将这些请求转换为底层物理硬件.
在此上下文中,VM被称为Guest,而其运行的环境称为主机.
LXC s:
Linux Containers(LXC)是操作系统级功能,可以在一个控制主机(LXC主机)上运行多个独立的Linux容器.Linux Containers是VM的轻量级替代品,因为它们不需要虚拟机管理程序即可.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都有自己的个体存在和重要性.
- 我很难理解_"(例如Centos主机上的Ubuntu容器,但它仍然是Linux)"_部分容器.我理解它的方式是容器共享主机内核.例如,如果我有运行Linux内核4.6的主机VM,则有几个客户机运行Linux内核2.4,2.6,3.2,4.1和4.4.如果我执行特定于该内核的命令,我将获得客户内核的行为(而不是主机).但是,如果我的访客VM现在是容器,那么执行的命令是由主机内核决定的吗?
- 您上面的"b"部分正是Docker人员对该技术所说的话.这意味着使开发**和**部署任务更容易.根据我作为开发人员和系统管理员的经验,我必须同意.
- 这是非常抽象的答案.我们需要用例何时使用/不使用Docker.这就是问题所在.每个人都可以找到Docker的样子,但只有少数人可以解释真实场景.
这里的大多数答案都是关于虚拟机的.我将在过去几年中使用Docker这个问题给你一个单行回复.就是这样:
现在,让我解释一下这意味着什么.虚拟机是他们自己的野兽.我想解释Docker将帮助您理解这一点,而不仅仅是解释虚拟机是什么.特别是因为这里有很多很好的答案,告诉你当他们说"虚拟机器"时,究竟是什么意思.所以...
Docker容器只是一个进程(及其子进程),它使用来自其他进程的主机系统内核中的cgroup进行分区.您可以通过ps aux
在主机上运行来实际查看Docker容器进程.例如,启动apache2
"在容器中"只是apache2
作为主机上的特殊进程启动.它刚刚与机器上的其他进程分开.值得注意的是,您的容器在容器化过程的生命周期之外不存在.当您的过程死亡时,您的容器会死亡.那是因为Docker pid 1
用您的应用程序替换容器内部(pid 1
通常是init系统).最后一点pid 1
非常重要.
对于每个容器进程使用的文件系统,Docker使用UnionFS -backed映像,这是您在执行时下载的内容docker pull ubuntu
.每个"图像"只是一系列图层和相关元数据.分层的概念在这里非常重要.每个图层只是从它下面的图层的变化.例如,当您在构建Docker容器时删除Dockerfile中的文件时,实际上只是在最后一层上创建了一个图层,上面写着"此文件已被删除".顺便说一句,这就是您可以从文件系统中删除大文件的原因,但图像仍占用相同数量的磁盘空间.文件仍然存在于当前文件下面的图层中.图层本身只是文件的tarball.您可以使用docker save --output /tmp/ubuntu.tar ubuntu
然后进行测试cd /tmp && tar xvf ubuntu.tar
.然后你可以看看周围.所有看起来像长哈希的目录实际上都是单独的层.每个包含files(layer.tar
)和metadata(json
)以及有关该特定层的信息.这些层只描述了对文件系统的更改,这些更改被保存为"在其原始状态之上"的层.在读取"当前"数据时,文件系统会读取数据,就像它只查看最顶层的更改一样.这就是为什么文件似乎被删除,即使它仍然存在于"之前"的图层中,因为文件系统只查看最顶层.这允许完全不同的容器共享其文件系统层,即使每个容器中最顶层的文件系统可能发生了一些重大更改.当容器共享基础图像层时,这可以为您节省大量磁盘空间.但是,当您通过卷将主机系统中的目录和文件装入容器时,这些卷会"绕过"UnionFS,因此更改不会存储在层中.
Docker中的网络是通过使用以太网桥(docker0
在主机上调用)和主机上每个容器的虚拟接口来实现的.它会docker0
为您的容器创建一个虚拟子网,以便彼此之间进行"通信".这里有许多网络选项,包括为容器创建自定义子网,以及"共享"主机网络堆栈以便容器直接访问的能力.
Docker移动得非常快.它的文档是我见过的最好的文档.它通常写得很好,简洁,准确.我建议您查看可用的文档以获取更多信息,并相信您在线阅读的任何文档,包括Stack Overflow.如果您有具体问题,我强烈建议您加入#docker
Freenode IRC并询问(您甚至可以使用Freenode的网络聊天!).
- "Docker只是运行流程的一种奇特方式,而不是虚拟机." 这是一个很棒的总结,谢谢!
Docker封装了一个具有所有依赖关系的应用程序.
虚拟器封装了一个操作系统,可以运行它通常可以在裸机上运行的任何应用程序.
- 我最喜欢这个答案.这很简单,直截了当.现在,人们已经基本了解了LXC和Virtualizer可以做什么,其他阅读的细节也是有意义的.
- @Phil它是在我首先阅读上面的详细答案之后做的.
它们都非常不同.Docker是轻量级的,使用LXC/libcontainer(依赖于内核命名空间和cgroup),并且没有机器/硬件仿真,如虚拟机管理程序,KVM.Xen很重.
Docker和LXC更适用于沙盒,容器化和资源隔离.它使用主机OS(目前只有Linux内核)克隆API,为IPC,NS(mount),网络,PID,UTS等提供命名空间.
内存,I/O,CPU等怎么样?这是使用cgroups控制的,您可以在其中创建具有特定资源(CPU,内存等)规范/限制的组,并将您的进程放在那里.在LXC之上,Docker提供了一个存储后端(http://www.projectatomic.io/docs/filesystems/),例如,union mount文件系统,您可以在其中添加图层并在不同的安装命名空间之间共享图层.
这是一个强大的功能,其中基本图像通常是只读的,并且只有当容器修改图层中的某些东西时它才会写入读写分区(也就是写入时的复制).它还提供许多其他包装器,如图像的注册表和版本控制.
使用普通的LXC,你需要带一些rootfs或共享rootfs,并在共享时,更改会反映在其他容器上.由于这些增加的功能很多,Docker比LXC更受欢迎.LXC在嵌入式环境中很受欢迎,用于实现暴露于外部实体(如网络和UI)的流程的安全性.Docker在云多租户环境中很受欢迎,预计会有一致的生产环境.
普通VM(例如,VirtualBox和VMware)使用管理程序,相关技术要么具有专用固件,要么成为第一个操作系统(主机操作系统或客户操作系统0)的第一层,要么是在主机操作系统上运行的软件为客户操作系统提供CPU,USB /配件,内存,网络等硬件仿真.在高安全性多租户环境中,虚拟机仍然(截至2015年)流行.
Docker/LXC几乎可以在任何便宜的硬件上运行(只要你有更新的内核,只有不到1 GB的内存也可以),而正常的VM需要至少2 GB的内存等,用它来做任何有意义的事情.但是主机操作系统上的Docker支持在Windows(截至2014年11月)等操作系统中不可用,因为可以在Windows,Linux和Mac上运行类型的VM.
这是来自docker/rightscale的照片:
1.轻量级
这可能是许多码头学习者的第一印象.
首先,docker镜像通常比VM镜像小,因此易于构建,复制,共享.
其次,Docker容器可以在几毫秒内启动,而VM可以在几秒钟内启动.
2.分层文件系统
这是Docker的另一个关键功能.图像具有图层,不同的图像可以共享图层,使其更加节省空间并且构建速度更快.
如果所有容器都使用Ubuntu作为基本映像,并非每个映像都有自己的文件系统,但是共享相同的下划线ubuntu文件,并且只有它们自己的应用程序数据不同.
3.共享操作系统内核
将容器视为流程!
在主机上运行的所有容器确实是一堆具有不同文件系统的进程.它们共享相同的操作系统内核,仅封装系统库和依赖项.
这对大多数情况都很好(没有额外的操作系统内核维护),但如果容器之间需要严格的隔离,则可能会出现问题.
为什么重要?
所有这些似乎都是改进,而不是革命.那么,量化积累会导致质的转变.
考虑应用程序部署.如果我们要部署新软件(服务)或升级软件(服务),最好更改配置文件和进程,而不是创建新VM.因为创建具有更新服务的VM,对其进行测试(在Dev&QA之间共享),部署到生产需要数小时甚至数天.如果出现任何问题,你必须重新开始,浪费更多时间.因此,使用配置管理工具(puppet,saltstack,chef等)安装新软件,首选下载新文件.
说到docker,就不可能使用新创建的docker容器来替换旧的docker容器.维护更容易!构建新映像,与QA共享,测试,部署它只需要几分钟(如果一切都是自动化的),在最坏的情况下需要几个小时.这称为不可变基础架构:不维护(升级)软件,而是创建新软件.
它改变了服务的交付方式.我们需要应用程序,但必须维护VM(这很痛苦,与我们的应用程序关系不大).Docker让您专注于应用程序并平滑一切.
Docker,基本上是容器,支持操作系统虚拟化,即您的应用程序认为它具有完整的操作系统实例,而VM支持硬件虚拟化.您觉得它是一台物理机器,您可以在其中启动任何操作系统.
在Docker中,运行的容器共享主机操作系统内核,而在VM中,它们拥有自己的操作系统文件.当您将应用程序部署到各种服务环境(例如"测试"或"生产")时,开发应用程序的环境(OS)将是相同的.
例如,如果您开发在端口4000上运行的Web服务器,当您将其部署到"测试"环境时,该端口已被其他程序使用,因此它将停止工作.在容器中有层; 您对操作系统所做的所有更改都将保存在一个或多个图层中,这些图层将成为图像的一部分,因此无论图像在何处,依赖关系都会出现.
在下面显示的示例中,主机有三个VM.为了使VM中的应用程序完全隔离,它们每个都有自己的OS文件,库和应用程序代码副本,以及操作系统的完整内存实例.
而下图显示了与容器相同的情况.这里,容器只是共享主机操作系统,包括内核和库,因此它们不需要启动操作系统,加载库或为这些文件支付专用内存成本.它们采用的唯一增量空间是应用程序在容器中运行所需的任何内存和磁盘空间.虽然应用程序的环境感觉像是一个专用的操作系统,但应用程序的部署就像它在专用主机上一样.容器化应用程序在几秒钟内启动,并且应用程序的更多实例可以适合机器而不是VM情况.
来源:https://azure.microsoft.com/en-us/blog/containers-docker-windows-and-trends/
有三种不同的设置可以提供堆栈来运行应用程序(这将有助于我们识别容器是什么以及什么使它比其他解决方案更强大):
1) Traditional Servers(bare metal)
2) Virtual machines (VMs)
3) Containers
1)传统服务器堆栈由运行操作系统的物理服务器和应用程序组成.
好处:
缺点:
- 部署时间非常慢
- 昂贵
- 浪费资源
- 难以扩展
- 难以迁移
- 复杂的配置
2)VM堆栈包括运行操作系统的物理服务器和管理虚拟机,共享资源和网络接口的虚拟机管理程序.每个Vm运行客户操作系统,应用程序或一组应用程序.
好处:
- 善用资源
- 易于扩展
- 易于备份和迁移
- 成本效益
- 灵活性
缺点:
- 资源分配存在问题
- 供应商锁定
- 复杂的配置
3)容器设置,与其他堆栈的关键区别是基于容器的虚拟化使用主机操作系统的内核来浏览多个隔离的客户端实例.这些来宾实例称为容器.主机可以是物理服务器或VM.
好处:
- 隔离
- 轻量级
- 资源有效
- 易于迁移
- 安全
- 低开销
- 镜子生产和开发环境
缺点:
- 相同的架构
- 资源繁重的应用
- 网络和安全问题.
通过将容器设置与其前身进行比较,我们可以得出结论,容器化是迄今为止我们所知道的最快,最有效,最安全的设置.容器是运行应用程序的隔离实例.Docker以某种方式启动容器,层使用默认存储驱动程序(Overlay驱动程序)获取运行时内存,这些驱动程序在几秒钟内运行,并且一旦我们提交到容器中,就会在其上创建copy-on-write层,从而支持执行容器.如果是VM,则需要大约一分钟才能将所有内容加载到虚拟化环境中.这些轻量级实例可以轻松更换,重建和移动.这使我们能够反映生产和开发环境,并在CI/CD流程中提供巨大帮助.容器可以提供的优势非常引人注目,它们肯定会留在这里.
和---关联:-
大多数软件都部署到许多环境中,通常至少有以下三种:
- 个人开发者个人电脑
- 共享开发者环境
- 个人测试仪PC
- 共享测试环境
- QA环境
- UAT环境
- 负载/性能测试
- 现场演出
- 生产
- 档案
还有以下因素需要考虑:
- 根据工作的性质,开发人员和测试人员都将拥有微妙或完全不同的PC配置
- 开发人员通常可以在不受公司或业务标准化规则控制的PC上进行开发(例如,在自己的机器上(通常是远程)开发的自由职业者或开源项目的贡献者,他们没有"雇用"或"签约"以配置他们的PC办法)
- 某些环境将由负载平衡配置中的固定数量的多台计算机组成
- 许多生产环境将根据流量级别动态(或"弹性地")创建和销毁基于云的服务器
正如您所看到的,组织的外推服务器总数很少以单个数字表示,通常是三位数,并且可以很容易地显着提高.
这一切都意味着首先创建一致的环境只是因为数量庞大(即使在绿色领域的情况下),但保持一致是完全不可能的,因为服务器数量很多,添加了新的服务器(动态或手动),来自o/s供应商,防病毒供应商,浏览器供应商等的自动更新,由开发人员或服务器技术人员执行的手动软件安装或配置更改等.让我重复一遍 - 它实际上(没有双关语意图)是不可能的保持环境一致(好吧,对于纯粹主义者来说,它可以完成,但它涉及大量的时间,精力和纪律,这正是为什么VM和容器(例如Docker)首先被设计出来的原因).
因此,更多地考虑您的问题"考虑到保持所有环境一致的极端困难,将软件部署到码头图像是否更容易,即使考虑到学习曲线?" .我想你会发现答案肯定会是"是" - 但是只有一种方法可以找到,在Stack Overflow上发布这个新问题.
有许多答案可以解释这些差异的更详细,但这是我非常简短的解释.
一个重要的区别是VM使用单独的内核来运行操作系统.这就是它很重的原因,需要时间来启动,消耗更多的系统资源.
在Docker中,容器与主机共享内核 ; 因此它重量轻,可以快速启动和停止.
在虚拟化中,资源在设置开始时分配,因此当虚拟机在许多时间空闲时,资源未被充分利用.在Docker中,容器没有分配固定数量的硬件资源,并且可以根据需要自由使用资源,因此具有高度可扩展性.
Docker使用UNION文件系统 .Docker使用写时复制技术来减少容器占用的内存空间.在这里阅读更多
使用虚拟机,我们有一台服务器,我们在该服务器上有一个主机操作系统,然后我们有一个虚拟机管理程序.然后运行在该虚拟机管理程序之上,我们有任意数量的客户操作系统,其中包含应用程序及其依赖二进制文件,以及该服务器上的库.它带来了整个客户操作系统.它非常重量级.您还可以在每台物理机上实际放置多少限制.
另一方面,Docker容器略有不同.我们有服务器.我们有主机操作系统.但在这种情况下,我们使用Docker引擎作为管理程序.在这种情况下,我们不会带来整个客户操作系统.我们带来了一个非常薄的操作系统层,容器可以向下进入主机操作系统,以便在那里获得内核功能.这使我们拥有一个非常轻量级的容器.
它所拥有的只是应用程序代码以及它所需的任何二进制文件和库.如果你想要它们,那么这些二进制文件和库实际上可以在不同的容器之间共享.这使我们能做的事情有很多.它们的启动时间要快得多.你不能在几秒钟之内就能站起来.同样地,快速降低它们......所以我们可以很快地扩大和缩小,我们稍后会看到它.
每个容器都认为它在自己的操作系统副本上运行.它有自己的文件系统,自己的注册表等,这是一种谎言.它实际上是虚拟化的.
资料来源:Kubernetes in Action.
我在生产环境中使用过Docker并且非常有用.当你习惯它时,你会发现它非常强大,可用于构建多容器和隔离环境.
Docker是基于LXC(Linux容器)开发的,可以在许多Linux发行版中完美运行,尤其是Ubuntu.
Docker容器是隔离的环境.top
在从Docker镜像创建的Docker容器中发出命令时,可以看到它.
除此之外,由于dockerFile配置,它们非常轻巧灵活.
例如,您可以创建一个Docker镜像并配置DockerFile,并告诉它例如何时运行,然后wget'the',apt-get'the',运行'some shell script',设置环境变量等等.
在微服务项目和架构中,Docker是一种非常可行的资产.您可以使用Docker,Docker swarm,Kubernetes和Docker Compose实现可扩展性,弹性和弹性.
Docker的另一个重要问题是Docker Hub及其社区.例如,我使用Prometheus,Grafana,Prometheus-JMX-Exporter和Dokcer实现了一个监控kafka的生态系统.
为此,我为zookeeper,kafka,Prometheus,Grafana和jmx-collector下载了已配置的Docker容器,然后使用yml文件为其中一些安装了我自己的配置,或者为了其他我在Docker容器中更改了一些文件和配置,我构建了一个整体系统用于在单台机器上使用多容器Docker监控kafka,具有隔离,可扩展性和弹性,可以轻松地将该架构移动到多个服务器中.
除了Docker Hub站点之外,还有另一个名为quay.io的站点,您可以使用它来拥有自己的Docker镜像仪表板并从中拉/推.您甚至可以将Docker Hub中的Docker映像导入到码头,然后在您自己的计算机上从码头运行它们.
注意:首先学习Docker看起来很复杂而且很难,但是当你习惯它时,如果没有它就无法工作.
我记得当我发出错误的命令或错误地删除我的容器和所有数据和配置时,使用Docker的第一天.
这里有很多很好的技术答案,它们清楚地讨论了 VM 和容器之间的区别以及 Docker 的起源。
对我来说,VM 和 Docker 之间的根本区别在于您如何管理应用程序的推广。
使用 VM,您可以将应用程序及其依赖项从一个 VM 提升到下一个 DEV,再到 UAT 到 PRD。
- 通常这些虚拟机会有不同的补丁和库。
- 多个应用程序共享一个 VM 的情况并不少见。这需要管理所有应用程序的配置和依赖项。
- 回退需要撤消 VM 中的更改。或者如果可能的话恢复它。
使用 Docker 的想法是,您将应用程序与其所需的库一起捆绑在自己的容器中,然后将整个容器提升为一个单元。
- 除了内核之外,补丁和库是相同的。
- 作为一般规则,每个容器只有一个应用程序,这简化了配置。
- 退出包括停止和删除容器。
因此,在最基本的层面上,使用 VM,您可以将应用程序及其依赖项提升为离散组件,而使用 Docker,您可以一次性提升所有内容。
是的,尽管 Kubernetes 或 Docker Swarm 等工具极大地简化了任务,但容器存在管理问题,包括管理它们。
这就是Docker自我介绍的方式:
因此Docker是基于容器的,这意味着您可以在当前计算机上运行图像和容器.它不包括像VM这样的操作系统,而是像一堆不同的工作包,如Java,Tomcat等.
如果您了解容器,您将获得Docker的功能以及它与VM的不同之处......
那么,什么是容器?
因此,如下图所示,每个容器都有一个单独的包,并在一台机器上运行,共享该机器的操作系统......它们安全且易于发货......