关于容器:Docker与虚拟机有何不同?

How is Docker different from a virtual machine?

我不断地重读Docker文档,试图理解Docker和完整的VM之间的区别。它如何能够提供完整的文件系统、独立的网络环境等,而不至于太重?

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


Docker最初使用Linux容器(lxc),但后来改为runc(以前称为libcontainer),它在与其主机相同的操作系统中运行。这允许它共享大量主机操作系统资源。此外,它使用分层文件系统(aufs)并管理网络。

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

因此,假设您有一个1 GB的容器映像;如果要使用完整的虚拟机,则需要有1 GB乘以X个所需的虚拟机。使用Docker和AUF,您可以在所有容器之间共享1 GB的大部分空间,如果您有1000个容器,那么容器操作系统的空间可能只有1 GB多一点(假设它们都运行相同的操作系统映像)。

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

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

每种类型的虚拟化系统都有优缺点。如果您希望使用有保证的资源实现完全隔离,那么完整的虚拟机就是一种方法。如果您只想将进程彼此隔离,并希望在一个合理大小的主机上运行大量进程,那么docker/lxc/runc似乎是解决问题的方法。

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

Why is deploying software to a docker image (if that's the right term) easier than simply deploying to a consistent production environment?

部署一致的生产环境说起来容易做起来难。即使您使用诸如chef和puppet之类的工具,在主机和环境之间也总会有操作系统更新和其他变化。

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

这对于测试很好;假设您有数千个需要连接到数据库的测试,并且每个测试都需要数据库的原始副本,并且将对数据进行更改。传统的方法是在每次测试后重置数据库,要么使用自定义代码,要么使用诸如Flyway之类的工具——这可能非常耗时,意味着必须连续运行测试。但是,使用Docker,您可以创建数据库的映像,并为每个测试运行一个实例,然后并行运行所有测试,因为您知道它们都将在数据库的同一快照上运行。由于测试是并行运行的,并且在Docker容器中,它们可以同时在同一个盒子上运行,并且应该完成得更快。试着用一个完整的虚拟机来做。

从评论…

Interesting! I suppose I'm still confused by the notion of"snapshot[ting] the OS". How does one do that without, well, making an image of the OS?

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


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

enter image description here

来源


了解虚拟化和容器如何在低级别工作可能会有所帮助。这会解决很多问题。

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

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

在这种情况下,VM管理器接管CPU环0(或较新CPU中的"根模式"),并截获来宾操作系统发出的所有特权调用,以创建来宾操作系统拥有自己硬件的假象。有趣的事实:在1998年之前,人们认为在x86体系结构中实现这一点是不可能的,因为没有办法进行这种拦截。vmware的人是第一个想到在内存中重写可执行字节以实现来宾操作系统的特权调用的人。

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

容器如何在低水平下工作?

大约在2006年,包括谷歌的一些员工在内的人们实现了新的内核级功能,称为名称空间(不过这个想法早在FreeBSD中就存在)。操作系统的一个功能是允许共享全局资源(如网络和磁盘)进行处理。如果这些全局资源包装在名称空间中,以便它们只对运行在同一名称空间中的进程可见,该怎么办?例如,您可以获取一块磁盘并将其放入命名空间X中,然后在命名空间Y中运行的进程看不到或无法访问它。同样,命名空间X中的进程无法访问分配给命名空间Y的内存中的任何内容。当然,x中的进程无法看到或与命名空间Y中的进程对话。这为全局资源提供了某种虚拟化和隔离。Docker就是这样工作的:每个容器在自己的名称空间中运行,但使用的内核与所有其他容器完全相同。隔离的发生是因为内核知道分配给进程的名称空间,并且在API调用期间,它确保进程只能访问自己名称空间中的资源。

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


我喜欢肯·科克伦的回答。

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

对我来说,它适合于面向开发人员的工具(如RPM、Debian软件包、Maven、NPM+Git)和操作工具(如Puppet、VMware、Xen)之间的差距,您可以将其命名为……

Why is deploying software to a docker image (if that's the right term) easier than simply deploying to a consistent production environment?

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

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

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

使用Docker生态系统,您将永远不需要在"小变化"(感谢aufs和注册表)上移动大约千兆字节,并且您不需要担心在运行时将应用程序打包到Docker容器中会降低性能。你不必担心那个图像的版本。

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

当然,您可以在vms中启动Docker容器(这是个好主意)。在虚拟机级别上减少服务器配置。以上都可以由码头工人来管理。

同时,Docker使用自己的实现"libcontainer"而不是lxc。但LXC仍然可用。


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

为了了解它与其他虚拟化的不同之处,我们来看看虚拟化及其类型。那么,就更容易理解其中的区别了。好的。

虚拟化好的。

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

管理程序好的。

管理程序负责创建来宾虚拟机在其上运行的虚拟环境。它监督客人系统,并确保在必要时将资源分配给客人。虚拟机监控程序位于物理机和虚拟机之间,为虚拟机提供虚拟化服务。为了实现这一点,它截获了虚拟机上的客户操作系统操作,并模拟了主机操作系统上的操作。好的。

虚拟化技术的快速发展,主要是在云端,通过允许在一个物理服务器上创建多个虚拟服务器,借助于管理程序(如Xen、VMware Player、KVM等),以及在商品处理器(如Intel VT AN)中集成硬件支持,进一步推动了虚拟化的使用。D AMD V好的。

虚拟化的类型好的。

虚拟化方法可以根据它如何向来宾操作系统模拟硬件和模拟来宾操作环境进行分类。主要有三种类型的虚拟化:好的。

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

仿真好的。

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

Emulation好的。

此类别中的示例包括vmware player、virtualbox、qemu、bochs、parallels等。好的。

准虚拟化好的。

准虚拟化,也称为类型1管理程序,直接在硬件上运行,或"裸机"上运行,并直接向在其上运行的虚拟机提供虚拟化服务。它帮助操作系统、虚拟化硬件和真正的硬件协作以获得最佳性能。这些管理程序通常占地面积很小,而且本身不需要大量资源。好的。

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

Paravirtualization好的。

基于容器的虚拟化好的。

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

Container-based virtualization好的。

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

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

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

Linux容器有几种管理工具,包括lxc、lxd、systemd nspawn、lmctfy、warden、linux vserver、openvz、docker等。好的。

容器与虚拟机好的。

与虚拟机不同,容器不需要启动操作系统内核,因此容器可以在不到一秒钟内创建。这一特性使得基于容器的虚拟化比其他虚拟化方法更加独特和可取。好的。

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

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

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

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

容器中的资源管理是通过CGroups实现的。CGroups不允许容器消耗比分配给它们的资源更多的资源。但是,到目前为止,主机的所有资源在虚拟机中都是可见的,但不能使用。这可以通过同时在容器和主机上运行tophtop来实现。所有环境的输出看起来都相似。好的。

更新:好的。

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

如果容器由于Linux内核中的可用特性而成为可能,那么显而易见的问题是,非Linux系统如何运行容器。Docker for Mac和Windows都使用Linux虚拟机来运行容器。Docker工具箱用于在虚拟机vms中运行容器。但是,最新的Docker在Windows中使用了Hyper-V,在Mac中使用了hypervisor.framework。好的。

现在,让我详细描述Docker for Mac如何运行容器。好的。

Docker for Mac使用https://github.com/moby/hyperkit模拟管理程序功能,hyperkit在其核心使用hypervisor.framework。hypervisor.framework是Mac的本机hypervisor解决方案。Hyperkit还分别使用vpnkit和datakit来命名网络和文件系统。好的。

Docker在Mac上运行的Linux虚拟机是只读的。但是,您可以通过运行以下命令来猛击它:好的。

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

现在,我们甚至可以检查这个虚拟机的内核版本:好的。

# uname -a
Linux linuxkit-025000000001 4.9.93-linuxkit-aufs #1 SMP Wed Jun 6 16:86_64 Linux
。好的。

所有容器都在此虚拟机中运行。好的。

hypervisor.framework有一些限制。因为docker没有在mac中公开docker0网络接口。所以,您不能从主机访问容器。到目前为止,docker0只在vm中可用。好的。

Hyper-V是Windows中的本机管理程序。他们还试图利用Windows10的功能以本机方式运行Linux系统。好的。好啊。


通过这篇文章,我们将得出vms和lxcs之间的一些区别。让我们先定义它们。

虚拟机:

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

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

LXCs:

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

现在,除非你被Alan(Zach Galifianakis,来自《宿醉》系列)下药,并在维加斯呆了一年,否则你会非常清楚Linux容器技术的巨大兴趣,如果我是一个在过去几个月里在世界各地引起轰动的容器项目,那就是Docker Leadi。一些人认为云计算环境应该放弃虚拟机(VM),并用容器替换它们,因为它们的开销较低,而且性能可能更好。

但最大的问题是,它是否可行?,是否明智?

a.lxcs的作用域是Linux的一个实例。它可能是不同风格的Linux(例如,CentOS主机上的Ubuntu容器,但它仍然是Linux)。同样,如果我们现在看一看虚拟机,基于Windows的容器的作用域会扩大到Windows的一个实例,它们的作用域会更广,并且使用的是管理程序,您不局限于操作系统Linux或Windows。

与虚拟机相比,LXC的管理费用低,性能更好。工具即建立在LXC技术基础上的Docker为开发人员提供了一个平台来运行他们的应用程序,同时也为操作人员提供了一个工具,允许他们在生产服务器或数据中心上部署相同的容器。它试图让运行应用程序的开发人员、启动和测试应用程序的开发人员和部署应用程序的操作人员之间的经验无缝衔接,因为这是所有摩擦的所在,DevOps的目的是打破这些筒仓。

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

放弃虚拟机目前还不现实。因此,虚拟机和LXC都有各自的存在和重要性。


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

Docker is just a fancy way to run a process, not a virtual machine.

Ok.

现在,让我详细解释一下这意味着什么。虚拟机是它们自己的野兽。我觉得解释Docker是什么比解释虚拟机更能帮助你理解这一点。尤其是因为这里有很多很好的答案,告诉你当人们说"虚拟机"时,他们的意思是什么。所以…好的。

Docker容器只是一个进程(及其子进程),它使用主机系统内核内的CGroups与其余进程分隔开。通过在主机上运行ps aux,您实际上可以看到Docker容器进程。例如,在容器中启动apache2只是作为主机上的一个特殊过程启动apache2。它只是从机器上的其他过程中分离出来的。重要的是要注意,容器不存在于容器化进程的生存期之外。当你的过程结束时,你的容器就结束了。这是因为Docker用您的应用程序替换了容器中的pid 1(pid 1通常是init系统)。关于pid 1的最后一点非常重要。好的。

该文件系统使用的的每个集装箱通过这些过程,它支持的图像unionfs码头,这是你当你的docker pull ubuntu下载。"意象"是就每一系列层和相关的元数据。分层的概念是非常重要的在这里。每一层是一个相变层,只是从它的下面。例如,当你删除的文件在你的dockerfile建设集装箱码头,而事实上,你只是创建一个层上的最后一层,说"此文件已被删除。这是一incidentally,为什么你可以删除的文件从您的大文件,但图像仍然需要检查的磁盘空间量。该文件仍然是这样,在下面一层的电流。他们都只是tarballs层)的文件。你可以测试这个与cd /tmp && tar xvf ubuntu.tardocker save --output /tmp/ubuntu.tar ubuntu然后。然后,你可以看看周围。所有这些目录的哈希值是真的,看起来像龙的单独的层。每一个文件(layer.tar)和元数据(关于这json)与特定的信息层。这些变化只是在文件系统层的描述,这是保存在"上"层,其原始状态。当阅读的"电流"数据,在文件系统读取数据,它是只读,在最顶层的变化。这就是为什么会出现在被删除的文件仍然存在,虽然它在"前"层,因为文件系统是只读,看着顶上的纤维层。这允许完全不同的容器文件系统层的共享他们的一些显着的变化,虽然有可能发生在文件系统中的其他层的顶部上的每个容器。这可以节省你的磁盘空间(吨的集装箱基地,当你分享他们的图像层。然而,当你安装的目录和文件从主机系统到您的集装箱由路卷,这些卷的unionfs"搭桥",是在不改变操作系统的存储层。

网络是采用以太网实现码头岸桥(称为docker0虚拟主机上的接口),和在每个主机上的容器。它的虚拟子网中扩展你的docker0容器彼此之间的交流"。这里有许多选项是创建一个自定义的子网的网络,包括在你的容器的能力,和"共享"你的主机的网络访问,你直接到堆栈容器。

码头是一个移动的非常快。该文档是一些最好的文档,我见过的。这是一个普遍良好的书面,简明、准确。我建议你检查文档的更多信息可以在文档上,信托你读任何其他使用,包括堆栈溢出。如果你有一个特定的问题,#dockerfreenode IRC网络使用的建议和要求的有(你可以使用聊天室甚至freenode的那!)。。。。。。。

好的。


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

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


它们都是非常不同的。Docker是轻量级的,使用lxc/libcontainer(它依赖于内核名称空间和cgroups),并且没有像hypervisor、kvm这样的机器/硬件仿真。Xen很重。

Docker和LXC更多的是用于沙箱化、集装箱化和资源隔离。它使用主机操作系统(目前只有Linux内核)的克隆API,该API为ipc、ns(mount)、network、pid、uts等提供名称空间。

内存、I/O、CPU等呢?这是使用cgroups控制的,在cgroups中,可以创建具有特定资源(CPU、内存等)规范/限制的组,并将进程放入其中。在LXC之上,Docker提供了一个存储后端(http://www.projectatomic.io/docs/filesystems/),例如Union Mount filesystem,您可以在其中添加层,并在不同的装载名称空间之间共享层。

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

对于普通的LXC,您需要使用一些rootfs或共享rootfs,并且在共享时,这些更改会反映在其他容器上。由于这些附加功能很多,Docker比LXC更受欢迎。LXC在嵌入式环境中很流行,用于围绕暴露于外部实体(如网络和UI)的进程实现安全性。Docker在云多租户环境中非常流行,在云多租户环境中需要一致的生产环境。

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

Docker/LXC几乎可以在任何便宜的硬件上运行(小于1 GB的内存也可以,只要您有更新的内核),而正常的虚拟机至少需要2 GB的内存等,才能对其进行任何有意义的操作。但主机操作系统上的Docker支持在Windows等操作系统中不可用(截至2014年11月),在Windows、Linux和Mac上可以运行5月份的虚拟机类型。

这是docker/rightscale的一张照片:Here is a pic from rightscale


1。轻量化

这可能是许多码头工人学习者的第一印象。

首先,Docker映像通常比VM映像小,使其易于构建、复制和共享。

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

2。分层文件系统

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

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

三。共享操作系统内核

把容器看作过程!

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

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

为什么重要?

所有这些似乎都是改进,而不是革命。定量积累导致质的转化。

考虑应用程序部署。如果我们想要部署一个新的软件(服务)或升级一个,最好更改配置文件和进程,而不是创建一个新的VM。因为使用更新的服务创建一个虚拟机,测试它(在开发人员和质量保证人员之间共享),部署到生产环境需要数小时,甚至数天。如果出了什么问题,你必须重新开始,浪费更多的时间。因此,使用配置管理工具(puppet、saltstack、chef等)安装新软件,最好下载新文件。

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

它转换服务的交付方式。我们需要应用程序,但必须维护虚拟机(这是一个难题,与我们的应用程序无关)。Docker使您专注于应用程序,并使所有东西变得平滑。


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

在Docker中,运行的容器共享主机操作系统内核,而在VM中,它们有自己的操作系统文件。在将应用程序部署到各种服务环境(如"测试"或"生产")时,开发应用程序的环境(操作系统)是相同的。

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

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

来源:https://azure.microsoft.com/en-us/blog/containers-docker-windows-and-trends/


有三种不同的设置可以提供一个堆栈来运行应用程序(这将有助于我们识别容器是什么以及它比其他解决方案强大的原因):

1
2
3
1) Traditional Servers(bare metal)
2) Virtual machines (VMs)
3) Containers

1)传统的服务器堆栈由运行操作系统和应用程序的物理服务器组成。

优势:

  • 资源利用

  • 隔离

缺点:

  • 部署时间非常慢
  • 昂贵的
  • 浪费的资源
  • 难以缩放
  • 难以迁移
  • 复杂配置

2)VM堆栈由运行操作系统的物理服务器和管理虚拟机、共享资源和网络接口的管理程序组成。每个虚拟机运行一个来宾操作系统、一个应用程序或一组应用程序。

优势:

  • 充分利用资源
  • 易于规模化
  • 易于备份和迁移
  • 成本效率
  • 灵活性

缺点:

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

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

优势:

  • 隔离
  • 轻量化
  • 资源有效性
  • 易迁移
  • 安全性
  • 低开销
  • 镜像生产开发环境

缺点:

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

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


有很多答案可以更详细地解释这些差异,但这里是我非常简短的解释。

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

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

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

Docker使用联合文件系统..Docker使用copy-on-write技术来减少容器消耗的内存空间。在这里阅读更多


关于:

"Why is deploying software to a docker image easier than simply
deploying to a consistent production environment ?"

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

  • 个人开发PC
  • 共享开发人员环境
  • 个人测试仪PC
  • 共享测试环境
  • 质量保证环境
  • UAT环境
  • 负载/性能测试
  • 现场分级
  • 生产
  • 档案文件
  • 还需要考虑以下因素:

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

    正如您所看到的,一个组织的外推服务器总数很少用一个数字表示,通常用三个数字表示,而且可以很容易地显著更高。

    这一切都意味着,仅仅因为数量庞大(即使是在绿场情况下),在一开始就创建一致的环境已经足够困难了,但考虑到服务器数量众多、添加新服务器(动态或手动)、O/S供应商、防病毒供应商、浏览器的自动更新,保持一致几乎是不可能的。供应商等,由开发人员或服务器技术人员执行的手动软件安装或配置更改等。让我重复一遍-实际上(没有双关语)不可能保持环境的一致性(好吧,对于纯粹主义者来说,这是可以做到的,但它涉及大量的时间、精力和纪律,这正是为什么vms集装箱(如码头工人)最初是设计出来的。

    因此,请更像这样思考您的问题:"考虑到保持所有环境一致性的极端困难,即使考虑到学习曲线,将软件部署到Docker映像是否更容易?"我想你会发现答案总是"是",但只有一种方法可以找到答案,把这个新问题贴在堆栈溢出上。


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

    Enter image description here

    另一方面,码头集装箱略有不同。我们有服务器。我们有主机操作系统。但在本例中,我们使用的是Docker引擎,而不是管理程序。在这种情况下,我们不会带来一个完整的客户操作系统。我们带来了一个非常薄的操作系统层,容器可以向下对话到主机操作系统中,以获得那里的内核功能。这样我们就有了一个非常轻的容器。

    它所拥有的只是应用程序代码以及它所需要的任何二进制文件和库。如果您希望这些二进制文件和库也可以在不同的容器之间共享。这使我们能够做的事情有很多。他们有更快的启动时间。你不能像那样在几秒钟内站起来。同样,尽快把它们取下来……所以我们可以很快地上下扩展,稍后再看。

    Enter image description here

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


    我已经在生产环境中使用了Docker,并且非常频繁地进行登台。当你习惯了它,你会发现它对于构建一个多容器和孤立的环境非常强大。

    Docker是基于LXC(Linux容器)开发的,在许多Linux发行版,特别是Ubuntu中都能很好地工作。

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

    此外,由于Dockerfile的配置,它们非常轻和灵活。

    例如,您可以创建一个Docker映像并配置一个Dockerfile,并告诉它,例如,当它运行时,wget"this"、apt get"that"、运行"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。e具有隔离性、可扩展性和弹性的机器,该架构可以轻松地移动到多个服务器中。

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

    注意:首先学习Docker似乎很复杂和困难,但是当你习惯了它之后,你就不能没有它去工作了。

    我记得在与Docker合作的最初几天,我发出了错误的命令,或者错误地删除了容器以及所有的数据和配置。


    Difference between how apps in VM use cpu vs containers

    资料来源:Kubernetes在行动。


    Docker就是这样介绍自己的:

    Docker is the company driving the container movement and the only
    container platform provider to address every application across the
    hybrid cloud. Today’s businesses are under pressure to digitally
    transform but are constrained by existing applications and
    infrastructure while rationalizing an increasingly diverse portfolio
    of clouds, datacenters and application architectures. Docker enables
    true independence between applications and infrastructure and
    developers and IT ops to unlock their potential and creates a model
    for better collaboration and innovation.

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

    如果你了解容器,你就会知道Docker是什么,它和vms有什么不同…

    那么,什么是容器?

    A container image is a lightweight, stand-alone, executable package of
    a piece of software that includes everything needed to run it: code,
    runtime, system tools, system libraries, settings. Available for both
    Linux and Windows based apps, containerized software will always run
    the same, regardless of the environment. Containers isolate software
    from its surroundings, for example differences between development and
    staging environments and help reduce conflicts between teams running
    different software on the same infrastructure.

    Docker

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


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

    对我来说,vms和docker的根本区别在于如何管理应用程序的升级。

    使用vms,您可以将应用程序及其依赖项从一个vm提升到下一个dev,从uat提升到prd。

  • 这些虚拟机通常会有不同的补丁和库。
  • 多个应用程序共享一个虚拟机并不少见。这需要管理所有应用程序的配置和依赖关系。
  • 退出需要撤消VM中的更改。或者在可能的情况下恢复。
  • 有了Docker,您可以将应用程序与它需要的库捆绑在自己的容器中,然后将整个容器作为一个单元进行升级。

  • 除了内核,补丁和库是相同的。
  • 一般来说,每个容器只有一个应用程序可以简化配置。
  • 退出包括停止和删除容器。
  • 因此,在最基本的vms级别上,您可以将应用程序及其依赖项作为离散组件进行升级,而在Docker级别上,您可以一次性升级所有内容。

    当然,容器也存在一些问题,包括管理它们,尽管像Kubernetes或Docker Swarm这样的工具大大简化了任务。