Docker与虚拟机有何不同?

我一直在重读Docker留档,试图理解Docker和完整虚拟机之间的区别。它如何提供完整的文件系统、隔离的网络环境等,而不会那么沉重?

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

881626 次浏览

Docker最初使用linux容器(LXC),但后来切换到runC(以前称为lib容器),它与其主机在同一操作系统中运行。这允许它共享大量主机操作系统资源。此外,它使用分层文件系统(AuFS)并管理网络。

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

所以,假设你有一个1 GB的容器映像;如果你想使用完整的虚拟机,你需要1 GB x你想要的虚拟机数量。使用Docker和AuFS,你可以在所有容器之间共享1 GB的大部分,如果你有1000个容器,你仍然可能只有超过1 GB的容器操作系统空间(假设它们都运行相同的操作系统映像)。

一个完整的虚拟化系统有自己的一组资源分配给它,并进行最小的共享。你得到了更多的隔离,但它要重得多(需要更多的资源)。使用Docker,你得到的隔离更少,但容器是轻量级的(需要更少的资源)。所以你可以轻松地在主机上运行数千个容器,它甚至不会闪烁。试着用Xen做到这一点,除非你有一个非常大的主机,否则我认为这是不可能的。

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

每种类型的虚拟化系统都有优点和缺点。如果你想在保证资源的情况下完全隔离,那么完整的虚拟机就是要走的路。如果你只是想将进程相互隔离,并想在合理大小的主机上运行大量进程,那么Docker/LXC/runC似乎是要走的路。

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

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

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

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

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

从评论…

有趣!我想我仍然对“快照操作系统”的概念感到困惑。在没有制作操作系统图像的情况下,如何做到这一点?

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

通过这篇文章,我们将绘制VM和LXC之间的一些区别。让我们首先定义它们。

虚拟机

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

在这种情况下,VM被称为来宾,而它运行的环境被称为主机。

LXC

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

现在,除非你被Alan(Zach Galifianakis-来自宿醉系列)下药并且已经在拉斯维加斯呆了一年,否则你会非常清楚对Linux容器技术的巨大兴趣,如果我具体地说,在过去几个月里在世界各地引起轰动的一个容器项目是Docker,导致一些呼应的观点,即云计算环境应该放弃虚拟机(VM)并用容器取代它们,因为它们的开销更低,性能可能更好。

但最大的问题是,这可行吗?这是明智的吗?

答:LXC的作用域是Linux的实例。它可能是不同风格的Linux(例如CentOS主机上的Ubuntu容器,但它仍然Linux。)类似地,基于Windows的容器现在的作用域是Windows的实例,如果我们看一下虚拟机,它们的作用域更广,使用虚拟机管理程序,你不仅限于操作系统Linux或Windows。

基于LXC技术构建的Docker工具为开发人员提供了运行应用的平台,同时为运营人员提供了工具,允许他们在生产服务器或数据中心部署相同的容器。它试图让运行应用、启动和测试应用的开发人员和部署应用的运营人员之间的体验无缝连接,因为这是所有摩擦的根源,运营模式的目的是打破这些孤岛。

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

现在放弃虚拟机是不现实的。所以VM和LXC都有自己的个体存在和重要性。

Docker封装一个应用程序及其所有依赖项。

虚拟化器封装了一个操作系统,该操作系统可以运行它通常可以在裸机上运行的任何应用程序。

我喜欢Ken Cochrane的回答

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

对我来说,它适合面向开发人员的工具之间的差距,比如rpm、debian包、Maven、npm+Git,以及木偶、威睿、Xen等运维工具。

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

你的问题假设一些一致的正式生产环境。但是如何保持一致呢?考虑一些数量(>10)的服务器和应用程序,管道中的阶段。

为了保持同步,您将开始使用Puppet、厨师或您自己的配置脚本、未发布的规则和/或大量留档……理论上,服务器可以无限期运行,并保持完全一致和最新。实践无法完全管理服务器的配置,因此配置漂移和运行服务器的意外更改的空间很大。

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

有了Docker生态系统,你永远不需要在“小改动”上移动千兆字节(感谢aufs和注册表),你也不需要担心在运行时将应用程序打包到Docker容器中会导致性能下降。你不需要担心该映像的版本。

最后,您甚至可以经常在Linux笔记本电脑上重现复杂的生产环境(如果在您的情况下不起作用,请不要打电话给我;))

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

P. S.同时Docker使用自己的实现“lib容器”而不是LXC。但LXC仍然可用。

它们都非常不同。Docker是轻量级的,使用LXC/lib容器(依赖于内核命名空间和cgroup),并且没有机器/硬件仿真,例如管理程序、KVM。Xen是沉重的。

Docker和LXC更多地用于沙盒、容器化和资源隔离。它使用主机操作系统(目前只有Linux内核)的克隆API,为IPC、NS(挂载)、网络、PID、UTS等提供命名空间。

内存、I/O、CPU等呢?这是使用cgroup控制的,你可以在其中创建具有特定资源(CPU、内存等)规范/限制的组,并将你的进程放在那里。在LXC之上,Docker提供了一个存储后端(http://www.projectatomic.io/docs/filesystems/),例如,联合挂载文件系统,你可以在其中添加图层并在不同挂载命名空间之间共享图层。

这是一个强大的功能,其中基本映像通常是只读的,只有当容器修改图层中的某些内容时,它才会将某些内容写入读写分区(又名写入时复制)。它还提供了许多其他包装器,例如注册表和映像版本控制。

使用普通的LXC,你需要附带一些rootfs或共享rootfs,当共享时,这些变化会反映在其他容器上。由于许多这些附加功能,Docker比LXC更受欢迎。LXC在嵌入式环境中很受欢迎,用于实现暴露于外部实体(如网络和UI)的进程的安全性。Docker在云多租户环境中很受欢迎,在那里需要一致的正式生产环境。

普通的虚拟机(例如,VirtualBox和威睿)使用虚拟机管理程序,相关技术要么具有成为第一个操作系统(主机操作系统或来宾操作系统0)的第一层的专用固件,要么具有在主机操作系统上运行的软件,以向来宾操作系统提供CPU、USB/配件、内存、网络等硬件仿真。虚拟机仍然(截至2015年)在高安全性多租户环境中流行。

Docker/LXC几乎可以在任何便宜的硬件上运行(只要你有更新的内核,不到1 GB的内存也可以),而普通虚拟机需要至少2 GB的内存等,才能用它做任何有意义的事情。但是主机操作系统上的Docker支持在Windows等操作系统中不可用(截至2014年11月),在Windows、Linux和Mac上可以运行各种类型的虚拟机。

这是来自docker/rightsize的图片:这是右刻度的图片

很好的答案。只是为了获得容器与虚拟机的图像表示,看看下面的一个。

在此处输入图片描述

来源

了解虚拟化和容器在低级别上的工作方式可能会有所帮助。这将澄清很多事情。

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

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

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

净效果是虚拟化允许您在同一硬件上运行两个完全不同的操作系统。每个来宾操作系统都经历了无融资创业、加载内核等所有过程。您可以拥有非常严格的安全性。例如,来宾操作系统无法完全访问主机操作系统或其他来宾,从而将事情搞砸。

容器如何在低级别上工作?

大约在2006,包括一些Google员工在内的人们实现了一个名为命名空间的新内核级功能(然而在存在于FreeBSD之前是长期的想法)。操作系统的一个功能是允许进程之间共享网络和磁盘等全局资源。如果这些全局资源被包裹在命名空间中,这样它们只对运行在同一命名空间中的进程可见呢?假设,你可以得到一块磁盘并将其放入命名空间X中,然后运行在命名空间Y中的进程无法看到或访问它。类似地,命名空间X中的进程无法访问分配给命名空间Y的内存中的任何东西。当然,X中的进程看不到命名空间Y中的进程,也无法与命名空间Y中的进程通信。这为全局资源提供了一种虚拟化和隔离。这就是Docker的工作原理:每个容器都在自己的命名空间中运行,但与所有其他容器一样完全使用相同内核。发生隔离是因为内核知道分配给进程的命名空间,并且在API调用期间,它确保进程只能访问自己命名空间中的资源。

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

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

为了了解它与其他虚拟化有何不同,让我们介绍一下虚拟化及其类型。然后,更容易理解那里的区别。

虚拟化

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

Hypervisor

虚拟机管理程序负责创建来宾虚拟机运行的虚拟环境。它监督来宾系统,并确保根据需要将资源分配给来宾。虚拟机管理程序位于物理机和虚拟机之间,为虚拟机提供虚拟化服务。为了实现它,它拦截虚拟机上的来宾操作系统操作,并模拟主机操作系统上的操作。

虚拟化技术的快速发展,主要是在云中,通过允许在Xen、威睿Player、KVM等管理程序的帮助下在单个物理服务器上创建多个虚拟服务器,以及在英特尔VT和AMD-V等商品处理器中整合硬件支持,进一步推动了虚拟化的使用。

虚拟化的类型

虚拟化方法可以根据它如何将硬件模拟到客户操作系统并模拟客户操作环境来分类。主要有三种类型的虚拟化:

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

仿真

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

仿真

此类别中的示例包括威睿Player、VirtualBox、QEMU、Bochs、Parallels等。

半虚拟化

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

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

半虚拟化

基于容器的虚拟化

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

基于容器的虚拟化

容器的概念是通过添加到内核版本2.6.24Linux命名空间特性实现的。容器将其ID添加到每个进程并为每个系统调用添加新的权限改造检查。它由克隆系统调用访问,允许创建先前全局命名空间的单独实例。

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

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

有几种管理工具可用于Linux容器,包括LXC、LXD、system d-nspawn、lmctfy、Warden、Linux-VServer、OpenVZ、Docker等。

容器vs虚拟机

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

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

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

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

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

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

更新时间:

Docker如何在非Linux系统中运行容器?

如果容器是由于Linux内核中可用的功能而成为可能的,那么显而易见的问题是非Linux系统如何运行容器。Docker for Mac和Windows都使用LinuxVM来运行容器。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中运行的LinuxVM是只读的。但是,您可以通过运行以下命令来Bash到它:

screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty

现在,我们甚至可以检查此VM的内核版本:

#uname-aLinuxlinuxkit-0250000000014.9.93-linuxkit-aufs#1 SMP 6月6日星期三16:86_64Linux。

所有容器都在此VM中运行。

有一些限制hypervisor.framework.因为Docker没有在Mac中暴露docker0的网络接口,所以你无法从主机访问容器。目前docker0只在虚拟机内部可用。

Hyper-v是Windows中的本地管理程序。他们还试图利用Windows 10的功能来本地运行Linux系统。

这里的大多数答案都是关于虚拟机的。我将给你一个对这个问题的单行回答,这个问题在过去几年使用Docker时对我帮助最大。它是这样的:

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

现在,让我再解释一下这是什么意思。虚拟机是它们自己的野兽。我觉得解释docker是什么比解释虚拟机是什么更能帮助你理解这一点。尤其是因为这里有许多很好的答案告诉你当他们说“虚拟机”时某人的确切含义。所以…

Docker容器只是一个进程(及其子进程),在主机系统内核中使用cgroup与其他进程隔离开来。实际上,你可以通过在主机上运行ps aux来查看你的Docker容器进程。例如,“在容器中”启动apache2只是作为主机上的一个特殊进程启动apache2。它刚刚与机器上的其他进程隔离开来。重要的是要注意,你的容器在容器化进程的生命周期之外不存在。当你的进程死亡时,你的容器也会死亡。这是因为Docker用你的应用程序替换了容器内的pid 1pid 1通常是初始化系统)。最后一点关于pid 1非常重要。

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

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

Docker发展非常快。它的留档是我见过的最好的留档之一。它通常写得很好,简洁,准确。我建议您查看可用的留档以获取更多信息,并相信留档而不是您在网上阅读的任何其他内容,包括Stack Overflow。如果您有特定的问题,我强烈建议您加入Freenode IRC上的#docker并在那里询问(您甚至可以使用Freenode的网络聊天!)。

关于:-

"为什么将软件部署到docker映像比简单地“部署到一致的正式生产环境?”

大多数软件都部署在许多环境中,通常至少有以下三种:

  1. 个人开发人员PC
  2. 共享开发者环境
  3. 个人测试仪PC
  4. 共享测试环境
  5. 质检环境
  6. UAT环境
  7. 负载/性能测试
  8. 直播分期
  9. 生产环节
  10. 存档

还有以下因素需要考虑:

  • 开发人员,甚至测试人员,都将拥有微妙或截然不同的PC配置,这取决于工作的性质
  • 开发人员通常可以在公司或业务标准化规则无法控制的PC上进行开发(例如,在自己的机器上开发的自由职业者(通常是远程)或开源项目的贡献者,他们没有“受雇”或“签约”以某种方式配置他们的PC)
  • 某些环境将由固定数量的多台机器组成,采用负载平衡配置
  • 许多生产环境将根据流量级别动态(或“弹性”)创建和销毁基于云的服务器

正如您所看到的,一个组织的外推服务器总数很少是单位数,通常是三位数,并且很容易显着更高。

这一切都意味着首先创建一致的环境是很难的,仅仅是因为庞大的容量(即使在绿色场景中),但是让它们保持一致几乎是不可能的给定大量的服务器,添加新服务器(动态或手动),来自o/s供应商的自动更新,防病毒供应商,浏览器供应商等,由开发人员或服务器技术人员执行的手动软件安装或配置更改,等等。Docker)首先被设计出来)。

所以把你的问题想象成这样“考虑到保持所有环境一致的极端困难,即使考虑到学习曲线,将软件部署到docker映像是否更容易?”。我想你会发现答案总是“是”-但只有一种方法可以找到答案,在Stack Overflow上发布这个新问题。

Docker,基本上是容器,支持操作系统虚拟化,即您的应用程序感觉它有一个完整的操作系统实例,而VM支持硬件虚拟化。你觉得它是一台物理机器,你可以在其中启动任何操作系统。

在Docker中,运行的容器共享主机操作系统内核,而在虚拟机中,它们有自己的操作系统文件。当您将App部署到各种服务环境(例如“测试”或“生产”)时,您研发App的环境(操作系统)将是相同的。

例如,如果您开发一个在端口4000上运行的Web服务器,当您将其部署到您的“测试”环境时,该端口已经被其他程序使用,因此它停止工作。容器中有层;您对操作系统所做的所有更改都将保存在一个或多个层中,这些层将成为映像的一部分,因此无论映像走到哪里,依赖关系都将存在。

在下面显示的示例中,主机有三个虚拟机。为了为虚拟机中的应用程序提供完全隔离,它们每个都有自己的操作系统文件、库和应用程序代码副本,以及操作系统的完整内存实例。没有容器而下图显示了容器的相同场景。在这里,容器只是共享主机操作系统,包括内核和库,因此它们不需要启动操作系统、加载库或为这些文件支付私有内存成本。它们唯一占用的增量空间是应用程序在容器中运行所需的任何内存和磁盘空间。虽然应用程序的环境感觉就像一个专用的操作系统,但应用程序的部署就像它在专用主机上一样。容器化的应用程序在几秒钟内启动,并且比虚拟机可以容纳更多的应用程序实例。输入图片描述

来源: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运行一个来宾操作系统、一个应用程序或一组应用程序。

优点:

  • 善用资源
  • 易于扩展
  • 易于备份和迁移
  • 成本效益
  • 灵活性

缺点:

  • 资源分配有问题
  • 供应商锁定
  • 复杂配置

3)容器设置,与其他堆栈的关键区别是基于容器的虚拟化使用主机操作系统的内核来管理多个孤立的来宾实例。这些来宾实例称为容器。主机可以是物理服务器或虚拟机。

优点:

  • 隔离
  • 轻量级
  • 资源效益
  • 易于迁移
  • 安全合规
  • 低开销
  • 镜像制作开发环境

缺点:

  • 相同的架构
  • 资源密集型应用
  • 网络和安全问题。

通过将容器设置与其前身进行比较,我们可以得出结论,容器化是迄今为止我们所知道的最快、资源最有效和最安全的设置。容器是运行应用程序的隔离实例。Docker以某种方式旋转容器,层使用默认存储驱动程序(覆盖驱动程序)获得运行时内存,这些驱动程序在几秒钟内运行,一旦我们提交到容器中,就会在其上创建写时复制层,从而为容器的执行提供动力。对于虚拟机,大约需要一分钟才能将所有内容加载到虚拟化环境中。这些轻量级实例可以轻松替换、重建和移动。这使我们能够镜像生产和开发环境,并对CI/CD流程提供了巨大帮助。容器可以提供的优势非常引人注目,因此它们肯定会留下来。

有许多答案更详细地解释了差异,但这是我非常简短的解释。

一个重要的区别是虚拟机使用单独的内核来运行操作系统。这就是它很重并且需要时间引导的原因,消耗更多的系统资源。

在Docker中,容器共享内核与主机;因此它是轻量级的,可以快速启动和停止。

在虚拟化中,资源是在设置开始时分配的,因此当虚拟机在许多时候处于空闲状态时,资源没有得到充分利用。在Docker中,容器没有分配固定数量的硬件资源,可以根据需求自由使用资源,因此具有高度可扩展性。

Docker使用UNION文件系统… Docker使用写时复制技术来减少容器消耗的内存空间。在这里阅读更多

我经常在生产环境和分期中使用Docker。当你习惯它时,你会发现它对于构建多容器和隔离环境非常强大。

Docker是基于LXC(Linux容器)开发的,在许多Linux发行版中运行良好,尤其是Ubuntu。

Docker容器是隔离的环境。当您在从Docker映像创建的Docker容器中发出top命令时,您可以看到它。

除此之外,由于dockerFile配置,它们非常轻量级和灵活。

例如,您可以创建一个Docker映像并配置一个DockerFile,并告诉它例如当它运行时,然后wget'this',apt-get'that',运行'一些外壳脚本',设置环境变量等。

在微服务项目和架构中,Docker是一种非常可行的资产。您可以使用Docker、Docker Sward、库伯内特斯和Docker Composs实现可扩展性、弹性和弹性。

关于Docker的另一个重要问题是Docker Hub及其社区。例如,我实现了一个使用Prometheus、Grafana、Prometheus-JMX-Ex的生态系统来监控kafka。

为了做到这一点,我下载了配置好的Docker容器,用于zooKeeper、kafka、Prometheus、Grafana和jmx-收集器,然后使用YAML文件为其中一些安装了我自己的配置,或者对于其他人,我在Docker容器中更改了一些文件和配置,我构建了一个完整的系统,用于在一台机器上使用多容器Dockers监控kafka,具有隔离性、可扩展性和弹性,该架构可以轻松移动到多个服务器中。

除了Docker Hub站点之外,还有另一个名为quay.io的站点,您可以使用它在那里拥有自己的Docker映像仪表板并从中拉/推。您甚至可以将Docker映像从Docker Hub导入到码头,然后在自己的机器上从码头运行它们。

注意:首先学习Docker似乎既复杂又困难,但是当你习惯了它,那么没有它你就无法工作。

我记得使用Docker的第一天,当我发出错误的命令或错误地删除我的容器以及所有数据和配置时。

1.轻量级

这可能是许多Docker学习者的第一印象。

首先,docker映像通常比VM映像小,可以轻松构建、复制、共享。

其次,Docker容器可以在几毫秒内启动,而VM可以在几秒钟内启动。

2.分层文件系统

这是Docker的另一个关键特性。图像有图层,不同的图像可以共享图层,使其更节省空间,构建速度更快。

如果所有容器都使用Ubuntu作为它们的基本映像,则不是每个映像都有自己的文件系统,而是共享相同的下划线ubuntu文件,并且只有它们自己的应用程序数据不同。

3.共享操作系统内核

将容器视为进程!

所有运行在主机上的容器实际上是一组具有不同文件系统的进程。它们共享相同的操作系统内核,仅封装系统库和依赖项。

这在大多数情况下是好的(没有额外的操作系统内核维护),但如果容器之间需要严格隔离,可能会出现问题。

为什么重要?

所有这些看起来都是改进,而不是革命。好吧,量的积累导致质的转变

想想应用程序部署。如果我们想部署或升级一个新软件(服务),最好更改配置文件和流程,而不是创建新的虚拟机。因为创建一个具有更新服务的虚拟机、测试(开发和QA共享),部署到生产环境需要几个小时,甚至几天。如果出现任何问题,你必须重新开始,浪费更多时间。所以,使用配置管理工具(木偶、saltstack、厨师等)安装新软件,下载新文件是首选。

谈到docker,用新创建的docker容器来替换旧的是不可能的。维护要容易得多!构建一个新映像,与QA共享,测试,部署只需要几分钟(如果一切都是自动化的),最坏的情况下需要几个小时。这被称为不变基础设施:不维护(升级)软件,而是创建一个新的。

它改变了服务的交付方式。我们想要应用程序,但必须维护虚拟机(这很痛苦,与我们的应用程序无关)。Docker让你专注于应用程序并平滑一切。

使用虚拟机,我们有一个服务器,我们在该服务器上有一个主机操作系统,然后我们有一个管理程序。然后在该管理程序之上运行,我们有任意数量的客户操作系统,其中包含应用程序及其依赖的二进制文件,以及该服务器上的库。它带来了整个客户操作系统。它是相当重量级的。此外,您实际可以在每台物理机器上放置多少也有限制。

在此处输入图片描述

另一方面,Docker容器略有不同。我们有服务器。我们有主机操作系统。但是而不是管理程序,在这种情况下,我们有docker引擎。在这种情况下,我们没有带来整个客户操作系统。我们带来了操作系统中非常薄的一层,容器可以与主机操作系统对话,以便获得那里的内核功能。这使我们能够拥有一个非常轻量级的容器。

它所拥有的只是应用程序代码以及它需要的任何二进制文件和库。如果你希望它们也是如此,这些二进制文件和库实际上可以在不同的容器之间共享。这使我们能够做的是很多事情。它们有更快的启动时间。你不能像那样在几秒钟内启动一个虚拟机。同样,尽快将它们关闭…所以我们可以非常快速地扩展和缩小,我们稍后会看到。

在此处输入图片描述

每个容器都认为它在自己的操作系统副本上运行。它有自己的文件系统、自己的注册表等,这是一种谎言。它实际上是虚拟化的。

docker是这样介绍自己的:

Docker是推动容器运动的公司,也是唯一容器平台提供商,以解决跨混合云。今天的企业面临数字化的压力转换,但受现有应用程序和基础设施,同时使日益多样化的投资组合合理化云、数据中心和应用程序架构。Docker支持应用程序和基础设施之间的真正独立性开发人员和IT运营来释放他们的潜力并创建一个模型为了更好的合作和创新。

所以docker是基于容器的,这意味着你有可以在当前机器上运行的映像和容器。它不包括像虚拟机这样的操作系统,而是像Java、Tomcat等不同的工作包包。

如果你了解容器,你就会知道Docker是什么,以及它与虚拟机有何不同。

那么,什么是容器?

容器映像是一个轻量级的、独立的、可执行的包一个软件,包括运行它所需的一切:代码,运行时、系统工具、系统库、设置。适用于两者Linux和基于Windows的应用程序,容器化软件将始终运行无论环境如何,都是一样的。容器隔离软件从它的周围环境,例如发展和发展之间的差异暂存环境并帮助减少运行团队之间的冲突不同的软件在同一个基础设施上。

Docker

因此,如下图所示,每个容器都有一个单独的包,并且在一台机器上运行共享该机器的操作系统……它们安全且易于运输……

这里有很多很好的技术答案,清楚地讨论了虚拟机和容器之间的区别以及Docker的起源。

对我来说,虚拟机和Docker之间的根本区别在于您如何管理应用程序的推广。

使用VM,您可以将应用程序及其依赖项从一个VM提升到下一个DEV,再到UAT再到PRD。

  1. 这些虚拟机通常会有不同的补丁和库。
  2. 多个应用程序共享一个VM的情况并不少见。这需要管理所有应用程序的配置和依赖关系。
  3. 备份需要撤消VM中的更改。如果可能,或恢复它。

使用Docker的想法是将您的应用程序与它需要的库捆绑在它自己的容器中,然后将整个容器作为一个单元进行推广。

  1. 除了内核之外,补丁和库是相同的。
  2. 作为一般规则,每个容器只有一个应用程序,这简化了配置。
  3. 回退包括停止和删除容器。

因此,在最基本的层面上,使用VM,您可以将应用程序及其依赖项作为离散组件进行推广,而使用Docker,您可以一次性推广所有内容。

是的,容器存在问题,包括管理它们,尽管像库伯内特斯或Docker Sward这样的工具大大简化了任务。

VM中的应用程序如何使用cpu与容器之间的差异

来源:库伯内特斯在行动。

在我看来,这取决于,从你的应用程序的需求可以看出,为什么决定部署到Docker,因为Docker根据其功能将应用程序分成小部分,这变得有效,因为当一个应用程序/功能出错时,它对其他应用程序没有影响,与使用完整的vm相比,它会更慢,配置更复杂,但在某些方面比docker更安全

docker留档(和自我解释)区分了“虚拟机”和“容器”。他们倾向于以一种不寻常的方式解释和使用事物。他们可以这样做,因为这取决于他们,他们在留档中写什么,也因为虚拟化的术语还不太准确。

事实上,Docker留档对“容器”的理解,是现实中的半虚拟化(有时是“OS级虚拟化”),相反,硬件虚拟化不是docker。

Docker是一个低质量的半虚拟化解决方案。容器与VM的区别是由docker开发发明的,以解释他们产品的严重缺点。

它之所以变得如此受欢迎,是因为它们“把火给普通人”,即它使Win10工作站上典型服务器(=Linux)环境/软件产品的简单使用成为可能。这也是我们容忍他们的小“细微差别”的原因。但这并不意味着我们也应该相信它。

由于Windows主机上的docker使用了HyperV中的嵌入式Linux,并且其容器已在其中运行,因此情况变得更加模糊。因此,Windows上的docker使用了组合的硬件和半虚拟化解决方案。

简而言之,Docker容器是低质量的虚拟机,具有巨大的优势和很多缺点。

Docker容器不使用任何硬件虚拟化。**它有助于使用容器虚拟机提供了硬件抽象,因此您可以运行多个操作系统。容器提供了操作系统抽象,因此您可以运行多个容器。
FeatureVirtual Machine(Docker) Containers
OS每个VM是否包含一个Operating System每个Docker容器包含一个Operating System
高/宽每个虚拟机都包含操作系统运行所需硬件的虚拟副本。没有虚拟化的H/W与容器
权重虚拟机很重--原因在上面--容器是轻量级的,因此,快速
必需的S/W虚拟化实现使用软件称为管理程序使用称为Docker的软件实现容器化
核心虚拟机提供虚拟硬件(或可以安装操作系统和其他程序的硬件)
抽象
引导时间创建需要很长时间(通常是几分钟),并且需要大量资源开销,因为它们除了要使用的软件之外还运行整个操作系统。

我将尝试从实际的和战术的的角度回答这个问题。

当您想安装不同的os平台时,您使用虚拟机

示例:Linux上的OSX或Windows来宾VM。

当您想安装一堆尝试部署和共享冲突的资源和图书馆的不同软件时,您使用容器

示例:不同容器上的Tensorflow-gpu的源代码构建和旧的二进制版本。

当你在多服务器多用户环境容器还提供计算负载平衡

容器速度快得多,没有内存和磁盘开销,可以直接使用硬件,因为它们由命名空间而不是仿真覆盖层(kvm、bios-uefi-virtio)分隔。您可以对它们进行集群并配置资源使用限制,确定优先级。

现实生活中的例子:

你是4朋友在家。1是机械工程师,P2是土木工程师,P3是编译内核的程序员,P4是人工智能工程师。

而不是一个服务器机箱专用于每个人。你把每个1个VM的4个服务器案例与GPU直通(设计VM)。然后你把4种不同的计算所有集装箱服务器。这样,当只有一人工作,所有服务器所有核心和所有GPU被用于一项任务通过mpi分布到每台服务器上的1种计算容器中时。或者如果其中四个工作同时所有工作项目均匀分布到所有服务器或根据他们的计算需求,如果没有另外配置的话。cpu_allowencess、.ram_allowances等…(我假设每个服务器都有两个GPU)