我不断重读Docker 文档,试图了解 Docker 和完整 VM 之间的区别。它如何在不那么重的情况下提供完整的文件系统、隔离的网络环境等?
为什么将软件部署到 Docker 映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
我不断重读Docker 文档,试图了解 Docker 和完整 VM 之间的区别。它如何在不那么重的情况下提供完整的文件系统、隔离的网络环境等?
为什么将软件部署到 Docker 映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
Docker 最初使用Linux Containers (LXC),但后来改用runC(以前称为libcontainer),它运行在与其主机相同的操作系统中。这允许它共享大量的主机操作系统资源。此外,它使用分层文件系统 ( AuFS ) 并管理网络。
AuFS 是一个分层文件系统,因此您可以将只读部分和写入部分合并在一起。可以将操作系统的公共部分设为只读(并在所有容器之间共享),然后为每个容器提供自己的挂载以供写入。
因此,假设您有一个 1 GB 的容器映像;如果您想使用完整的 VM,则需要 1 GB x 所需的 VM 数。使用 Docker 和 AuFS,您可以在所有容器之间共享 1 GB 的大部分空间,如果您有 1000 个容器,您仍然可能只有 1 GB 多一点的空间用于容器操作系统(假设它们都运行相同的操作系统映像) .
一个完整的虚拟化系统获得分配给它自己的一组资源,并进行最少的共享。你得到更多的隔离,但它更重(需要更多的资源)。使用 Docker,您可以获得更少的隔离,但容器是轻量级的(需要更少的资源)。因此,您可以轻松地在主机上运行数千个容器,而且它甚至不会闪烁。试着用 Xen 来做,除非你有一个非常大的主机,否则我认为这是不可能的。
一个完整的虚拟化系统通常需要几分钟才能启动,而 Docker/LXC/runC 容器需要几秒钟,通常甚至不到一秒钟。
每种类型的虚拟化系统各有利弊。如果您想要完全隔离并保证资源,那么完整的 VM 是您的最佳选择。如果您只是想将进程彼此隔离并希望在合理大小的主机上运行大量进程,那么 Docker/LXC/runC 似乎是要走的路。
有关更多信息,请查看这组博客文章,这些文章很好地解释了 LXC 的工作原理。
为什么将软件部署到 docker 映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
部署一致的生产环境说起来容易做起来难。即使您使用Chef和Puppet 之类的工具,也总会有操作系统更新和其他在主机和环境之间发生变化的事情。
Docker 使您能够将操作系统快照到共享映像中,并使其易于部署在其他 Docker 主机上。在本地,dev、qa、prod 等:都是相同的图像。当然,您可以使用其他工具来做到这一点,但几乎没有那么容易或快速。
这非常适合测试;假设您有数千个测试需要连接到数据库,并且每个测试都需要数据库的原始副本并将更改数据。经典的方法是在每次测试后使用自定义代码或Flyway等工具重置数据库- 这可能非常耗时,并且意味着必须连续运行测试。但是,使用 Docker,您可以创建数据库的映像并在每个测试中运行一个实例,然后并行运行所有测试,因为您知道它们都将针对同一数据库快照运行。由于测试是在 Docker 容器中并行运行的,因此它们可以同时在同一个盒子上运行,并且应该更快地完成。尝试使用完整的 VM 执行此操作。
从评论...
有趣的!我想我仍然对“快照[ting] OS”的概念感到困惑。如果没有制作操作系统的图像,如何做到这一点?
好吧,让我们看看我能不能解释一下。您从一个基础映像开始,然后进行更改,并使用 docker 提交这些更改,然后它会创建一个映像。此图像仅包含与基础的差异。当你想运行你的镜像时,你还需要基础,它使用分层文件系统将你的镜像分层在基础之上:如上所述,Docker 使用 AuFS。AuFS 将不同的层合并在一起,你得到你想要的;你只需要运行它。您可以继续添加越来越多的图像(层),它将继续只保存差异。由于 Docker 通常构建在来自注册表的现成映像之上,因此您很少需要自己“快照”整个操作系统。
了解虚拟化和容器如何在低级别工作可能会有所帮助。这将清除很多事情。
注意:我在下面的描述中进行了一些简化。有关更多信息,请参阅参考资料。
虚拟化如何在低级别工作?
在这种情况下,VM 管理器接管 CPU 环 0(或较新 CPU 中的“根模式”)并拦截来宾操作系统进行的所有特权调用,以制造来宾操作系统拥有自己的硬件的假象。有趣的事实:在 1998 年之前,人们认为在 x86 架构上实现这一点是不可能的,因为没有办法进行这种拦截。VMware 的人是第一个想到重写内存中的可执行字节以实现来宾操作系统的特权调用的人。
最终效果是虚拟化允许您在同一硬件上运行两个完全不同的操作系统。每个客户操作系统都会经历引导、加载内核等所有过程。您可以拥有非常严格的安全性。例如,客户操作系统无法获得对主机操作系统或其他客户的完全访问权限,从而搞砸了。
容器如何在低级别工作?
大约在2006 年,包括一些 Google 员工在内的人们实现了一个新的内核级功能,称为命名空间(不过这个想法早在FreeBSD 中就已经存在了))。操作系统的一项功能是允许进程之间共享网络和磁盘等全局资源。如果这些全局资源被包装在命名空间中以便它们只对在同一命名空间中运行的那些进程可见怎么办?比如说,您可以获得一块磁盘并将其放在命名空间 X 中,然后在命名空间 Y 中运行的进程无法看到或访问它。同样,命名空间 X 中的进程无法访问分配给命名空间 Y 的内存中的任何内容。当然,X 中的进程无法看到或与命名空间 Y 中的进程通信。这为全局资源提供了一种虚拟化和隔离。这就是 Docker 的工作方式:每个容器在自己的命名空间中运行,但使用完全相同内核和所有其他容器一样。发生隔离是因为内核知道分配给进程的命名空间,并且在 API 调用期间,它确保进程只能访问其自己的命名空间中的资源。
容器与虚拟机的局限性现在应该很明显了:您不能像在虚拟机中那样在容器中运行完全不同的操作系统。但是,您可以运行不同的 Linux 发行版,因为它们共享相同的内核。隔离级别不如虚拟机强。事实上,在早期的实现中,有一种方法可以让“guest”容器接管主机。您还可以看到,当您加载新容器时,操作系统的全新副本不会像在 VM 中那样启动。所有容器共享同一个内核. 这就是容器重量轻的原因。同样与 VM 不同的是,您不必为容器预先分配大量内存,因为我们没有运行操作系统的新副本。这允许在一个操作系统上运行数千个容器,同时对它们进行沙箱化,如果我们在它们自己的虚拟机中运行操作系统的单独副本,这可能是不可能的。
我喜欢Ken Cochrane 的回答。
但我想补充一点额外的观点,这里不详细介绍。在我看来,Docker 在整个过程中也有所不同。与 VM 相比,Docker 不仅(仅)关于硬件的最佳资源共享,而且它提供了一个用于打包应用程序的“系统”(作为一组微服务是可取的,但不是必须的)。
对我来说,它一方面适合面向开发人员的工具(如 rpm、Debian软件包、Maven、npm + Git)与诸如Puppet、VMware、Xen 等运维工具之间的差距……
为什么将软件部署到 docker 映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
您的问题假设一些一致的生产环境。但是如何保持一致呢? 考虑一些(>10)服务器和应用程序,管道中的阶段。
为了保持同步,您将开始使用 Puppet、Chef或您自己的配置脚本、未发布的规则和/或大量文档……理论上服务器可以无限期地运行,并保持完全一致和最新。实践无法完全管理服务器的配置,因此配置漂移和运行服务器的意外更改存在相当大的范围。
所以有一种已知的模式可以避免这种情况,即所谓的不可变服务器。但是不可变的服务器模式并不受欢迎。主要是因为在 Docker 之前使用的虚拟机的限制。处理几G的大图,把那些大图搬来搬去,只是为了改变应用程序中的一些领域,非常非常费力。可以理解...
使用 Docker 生态系统,您将永远不需要在“小改动”上移动千兆字节(感谢 aufs 和 Registry),并且您无需担心在运行时将应用程序打包到 Docker 容器中会降低性能。您无需担心该图像的版本。
最后,您甚至可以经常在 Linux 笔记本电脑上重现复杂的生产环境(如果在您的情况下不起作用,请不要打电话给我;))
当然,您可以在 VM 中启动 Docker 容器(这是个好主意)。减少 VM 级别的服务器配置。以上都可以由 Docker 管理。
PS 同时 Docker 使用自己的实现“libcontainer”而不是 LXC。但 LXC 仍然可用。
Docker 不是一种虚拟化方法。它依赖于实际实现基于容器的虚拟化或操作系统级虚拟化的其他工具。为此,Docker 最初使用 LXC 驱动程序,然后转移到 libcontainer,现在更名为 runc。Docker 主要专注于在应用程序容器内自动部署应用程序。应用程序容器旨在打包和运行单个服务,而系统容器旨在运行多个进程,如虚拟机。因此,Docker 被认为是容器化系统上的容器管理或应用程序部署工具。
为了了解它与其他虚拟化有何不同,让我们来看看虚拟化及其类型。然后,更容易理解那里有什么区别。
虚拟化
在其构想形式中,它被认为是一种逻辑划分大型机以允许多个应用程序同时运行的方法。然而,当公司和开源社区能够提供一种以一种或另一种方式处理特权指令的方法并允许多个操作系统在单个基于 x86 的系统上同时运行时,情况发生了巨大变化。
管理程序
管理程序处理创建来宾虚拟机运行的虚拟环境。它监督来宾系统并确保根据需要将资源分配给来宾。管理程序位于物理机和虚拟机之间,为虚拟机提供虚拟化服务。为了实现它,它拦截虚拟机上的客户操作系统操作并模拟主机操作系统上的操作。
虚拟化技术(主要是在云中)的快速发展进一步推动了虚拟化的使用,允许在 Xen、VMware Player、KVM 等管理程序的帮助下在单个物理服务器上创建多个虚拟服务器,以及在商用处理器中加入硬件支持,例如 Intel VT 和 AMD-V。
虚拟化类型
虚拟化方法可以根据它如何模仿客户操作系统的硬件和模拟客户操作环境来分类。首先,存在三种类型的虚拟化:
仿真
仿真,也称为完全虚拟化,完全在软件中运行虚拟机操作系统内核。此类型中使用的管理程序称为类型 2 管理程序。它安装在主机操作系统的顶部,负责将客户操作系统内核代码转换为软件指令。翻译完全在软件中完成,不需要硬件参与。仿真使运行任何支持被仿真环境的未修改操作系统成为可能。这种类型的虚拟化的缺点是额外的系统资源开销,与其他类型的虚拟化相比会导致性能下降。
此类别中的示例包括 VMware Player、VirtualBox、QEMU、Bochs、Parallels 等。
半虚拟化
准虚拟化,也称为 Type 1 hypervisor,直接在硬件上运行,或“裸机”,并直接为运行在其上的虚拟机提供虚拟化服务。它帮助操作系统、虚拟化硬件和真实硬件协同工作以实现最佳性能。这些虚拟机管理程序通常占用的空间很小,并且它们本身不需要大量资源。
此类别中的示例包括 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 镜像)体积较小,因此容器镜像易于分发。
容器中的资源管理是通过 cgroups 实现的。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 系统。
这里的大多数答案都是关于虚拟机的。我将给你一个简单的回答这个问题,这个问题在过去几年使用 Docker 对我帮助最大。是这样的:
Docker 只是一种运行进程的奇特方式,而不是虚拟机。
现在,让我再解释一下这意味着什么。虚拟机是它们自己的野兽。我觉得解释Docker是什么比解释虚拟机是什么更能帮助你理解这一点。特别是因为这里有很多很好的答案可以准确地告诉您某人说“虚拟机”时的意思。所以...
Docker 容器只是一个进程(及其子进程),使用主机系统内核中的cgroups将其与其余进程区分开来。您实际上可以通过ps aux
在主机上运行来查看您的 Docker 容器进程。例如,apache2
“在容器中”启动只是apache2
作为主机上的一个特殊进程启动。它只是与机器上的其他进程分开。请务必注意,您的容器不存在于容器化进程的生命周期之外。当您的进程死亡时,您的容器也会死亡。那是因为 Docker 用pid 1
您的应用程序替换了您的容器内部(pid 1
通常是 init 系统)。最后一点pid 1
非常重要。
至于每个容器进程使用的文件系统,Docker 使用UnionFS支持的映像,这是您在执行docker pull ubuntu
. 每个“图像”只是一系列层和相关的元数据。分层的概念在这里非常重要。每一层都只是它下面的层的变化。例如,当您在构建 Docker 容器时删除 Dockerfile 中的文件时,实际上只是在最后一层之上创建了一个层,上面写着“此文件已被删除”。顺便说一句,这就是为什么您可以从文件系统中删除一个大文件,但该映像仍占用相同数量的磁盘空间。该文件仍然存在,位于当前文件下方的图层中。层本身只是文件的压缩包。你可以用docker save --output /tmp/ubuntu.tar ubuntu
然后cd /tmp && tar xvf ubuntu.tar
。然后你可以四处看看。所有那些看起来像长哈希的目录实际上都是单独的层。每一个都包含文件 ( layer.tar
) 和元数据 (json
) 以及有关该特定层的信息。这些层只是描述了对文件系统的更改,这些更改被保存为“在”其原始状态之上的一个层。当读取“当前”数据时,文件系统读取数据,就好像它只查看最顶层的更改一样。这就是文件似乎被删除的原因,即使它仍然存在于“先前”层中,因为文件系统只查看最顶层。这允许完全不同的容器共享它们的文件系统层,即使每个容器中最顶层的文件系统可能发生了一些重大变化。当你的容器共享它们的基础镜像层时,这可以为你节省大量的磁盘空间。然而,
Docker 中的网络是通过使用以太网桥(docker0
在主机上调用)和主机上每个容器的虚拟接口来实现的。它为您的容器创建了一个虚拟子网,docker0
以便彼此“之间”进行通信。这里有许多网络选项,包括为您的容器创建自定义子网,以及“共享”主机的网络堆栈以供容器直接访问的能力。
Docker 的发展速度非常快。它的文档是我见过的最好的文档之一。它通常写得很好,简洁而准确。我建议您查看可用的文档以获取更多信息,并信任该文档而不是您在线阅读的任何其他内容,包括 Stack Overflow。如果您有具体问题,我强烈建议您加入#docker
Freenode IRC 并在那里提问(您甚至可以使用 Freenode 的网络聊天!)。
通过这篇文章,我们将画出 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。)类似地,如果我们查看 VM,基于 Windows 的容器现在被限定为 Windows 实例,它们具有更广泛的范围并使用管理程序您不限于操作系统 Linux 或 Windows。
湾。与 VM 相比,LXC 的开销较低且性能更好。工具即。建立在 LXC 技术的肩膀上的 Docker 为开发人员提供了一个运行其应用程序的平台,同时为运维人员提供了一种工具,使他们能够在生产服务器或数据中心上部署相同的容器。它试图使运行应用程序、启动和测试应用程序的开发人员与部署该应用程序的运维人员之间的体验无缝,因为这是所有摩擦的所在,而 DevOps 的目的是打破这些孤岛。
因此,最好的方法是云基础设施提供商应该提倡适当使用 VM 和 LXC,因为它们都适合处理特定的工作负载和场景。
到目前为止,放弃 VM 是不切实际的。因此,VM 和 LXC 都有各自的存在和重要性。
Docker 封装了一个应用程序及其所有依赖项。
虚拟器封装了一个操作系统,该操作系统可以运行通常可以在裸机上运行的任何应用程序。
他们都非常不同。Docker 是轻量级的,使用 LXC/libcontainer(依赖于内核命名空间和 cgroups),并且没有机器/硬件仿真,例如虚拟机管理程序、KVM。Xen 其中很重。
Docker 和 LXC 更多地用于沙盒、容器化和资源隔离。它使用主机操作系统(目前只有 Linux 内核)的克隆 API,为 IPC、NS(挂载)、网络、PID、UTS 等提供命名空间。
内存、I/O、CPU 等呢?这是使用 cgroups 控制的,您可以在其中创建具有特定资源(CPU、内存等)规范/限制的组并将您的进程放在那里。在 LXC 之上,Docker 提供了一个存储后端(http://www.projectatomic.io/docs/filesystems/),例如联合挂载文件系统,您可以在其中添加层并在不同的挂载命名空间之间共享层。
这是一个强大的功能,其中基础镜像通常是只读的,只有当容器修改层中的某些内容时,它才会将某些内容写入读写分区(也就是写时复制)。它还提供了许多其他包装器,例如镜像的注册表和版本控制。
使用普通的 LXC,您需要附带一些 rootfs 或共享 rootfs,并且在共享时,更改会反映在其他容器上。由于这些附加功能很多,Docker 比 LXC 更受欢迎。LXC 在嵌入式环境中很流行,用于围绕暴露给外部实体(如网络和 UI)的流程实施安全性。Docker 在需要一致的生产环境的云多租户环境中很受欢迎。
普通虚拟机(例如,VirtualBox 和 VMware)使用虚拟机管理程序,相关技术要么具有成为第一个操作系统(主机操作系统或客户操作系统 0)的第一层的专用固件,要么具有在主机操作系统上运行的软件为客户操作系统提供硬件仿真,例如 CPU、USB/附件、内存、网络等。虚拟机(截至 2015 年)在高安全性多租户环境中仍然很流行。
Docker/LXC 几乎可以在任何便宜的硬件上运行(只要你有更新的内核,少于 1 GB 的内存也可以),而普通 VM 需要至少 2 GB 的内存等,才能用它做任何有意义的事情. 但是主机操作系统上的 Docker 支持在 Windows 等操作系统中不可用(截至 2014 年 11 月),在 Windows、Linux 和 Mac 上可以运行多种类型的虚拟机。
这可能是很多 docker 学习者的第一印象。
首先,docker 镜像通常比 VM 镜像小,便于构建、复制和共享。
其次,Docker 容器可以在几毫秒内启动,而 VM 在几秒钟内启动。
这是 Docker 的另一个关键特性。图像有图层,不同的图像可以共享图层,更节省空间,构建速度更快。
如果所有容器都使用 Ubuntu 作为其基础镜像,则并非每个镜像都有自己的文件系统,而是共享相同的下划线 ubuntu 文件,只是各自的应用程序数据不同。
将容器视为进程!
在主机上运行的所有容器确实是一堆具有不同文件系统的进程。它们共享相同的操作系统内核,仅封装系统库和依赖项。
这在大多数情况下都很好(无需维护额外的操作系统内核),但如果容器之间需要严格隔离,则可能会出现问题。
所有这些似乎都是改进,而不是革命。那么,量的积累导致质的转变。
考虑应用程序部署。如果我们想部署一个新的软件(服务)或升级一个,最好改变配置文件和进程,而不是创建一个新的虚拟机。因为创建具有更新服务的 VM、对其进行测试(在 Dev 和 QA 之间共享)、部署到生产需要数小时甚至数天。如果出现任何问题,您必须重新开始,浪费更多时间。因此,使用配置管理工具(puppet、saltstack、chef 等)安装新软件,下载新文件是首选。
对于 docker,不可能使用新创建的 docker 容器来替换旧的。维护要容易得多!构建一个新图像,与 QA 共享,测试它,部署它只需要几分钟(如果一切都是自动化的),最坏的情况是几个小时。这被称为不可变的基础设施:不要维护(升级)软件,而是创建一个新的。
它改变了服务的交付方式。我们想要应用程序,但必须维护虚拟机(这很痛苦,与我们的应用程序无关)。Docker 让您专注于应用程序并使一切变得顺畅。
Docker,基本上是容器,支持操作系统虚拟化,即你的应用程序感觉它有一个完整的操作系统实例,而 VM 支持硬件虚拟化。您会觉得它是一台物理机器,您可以在其中启动任何操作系统。
在 Docker 中,运行的容器共享主机操作系统内核,而在虚拟机中,它们有自己的操作系统文件。当您将应用程序部署到各种服务环境(例如“测试”或“生产”)时,开发应用程序的环境(操作系统)将是相同的。
例如,如果您开发了一个在端口 4000 上运行的 Web 服务器,当您将其部署到“测试”环境时,该端口已被其他程序使用,因此它停止工作。在容器中有层;您对操作系统所做的所有更改都将保存在一个或多个层中,并且这些层将成为图像的一部分,因此无论图像走到哪里,依赖关系也会出现。
在下面显示的示例中,主机具有三个 VM。为了使虚拟机中的应用程序完全隔离,它们每个都有自己的操作系统文件、库和应用程序代码的副本,以及操作系统的完整内存实例。 而下图显示了与容器相同的场景。在这里,容器只是共享主机操作系统,包括内核和库,因此它们不需要启动操作系统、加载库或为这些文件支付私有内存成本。它们占用的唯一增量空间是应用程序在容器中运行所需的任何内存和磁盘空间。虽然应用程序的环境感觉像是一个专用操作系统,但应用程序的部署就像它在专用主机上一样。容器化应用程序可以在几秒钟内启动,并且与 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 堆栈由运行操作系统的物理服务器和管理虚拟机、共享资源和网络接口的管理程序组成。每个虚拟机都运行一个客户操作系统、一个应用程序或一组应用程序。
优点:
缺点:
3)容器设置,与其他堆栈的主要区别是基于容器的虚拟化使用主机操作系统的内核来运行多个隔离的来宾实例。这些来宾实例称为容器。主机可以是物理服务器或虚拟机。
优点:
缺点:
通过将容器设置与其前身进行比较,我们可以得出结论,容器化是迄今为止我们所知道的最快、最具资源效率和最安全的设置。容器是运行您的应用程序的隔离实例。Docker 以某种方式启动容器,层使用默认存储驱动程序(覆盖驱动程序)获得运行时内存,这些驱动程序在几秒钟内运行,一旦我们提交到容器中,就会在其之上创建写时复制层,从而为执行提供动力容器。如果是虚拟机,将需要大约一分钟的时间将所有内容加载到虚拟化环境中。这些轻量级实例可以轻松替换、重建和移动。这使我们能够镜像生产和开发环境,并且对 CI/CD 流程有巨大帮助。容器可以提供的优势是如此引人注目,以至于它们肯定会继续存在。
和---关联:-
“为什么将软件部署到 docker 映像比简单地部署到一致的生产环境更容易?”
大多数软件都部署到许多环境中,通常至少是以下三个环境:
还有以下几个因素需要考虑:
正如您所看到的,一个组织的服务器总数推断很少是个位数,通常是三位数,而且很容易显着更高。
这一切都意味着,仅仅因为数量庞大(即使在绿地场景中),首先创建一致的环境已经足够困难了,但是考虑到大量服务器、添加新服务器(动态或手动)、来自操作系统供应商、防病毒供应商、浏览器供应商等的自动更新、由开发人员或服务器技术人员执行的手动软件安装或配置更改等。让我重复一遍——这实际上(没有双关语)是不可能的保持环境一致(好吧,对于纯粹主义者来说,这是可以做到的,但它需要大量的时间、精力和纪律,这正是最初设计 VM 和容器(例如 Docker)的原因)。
所以把你的问题想得更像这样“鉴于保持所有环境一致的极端困难,即使考虑到学习曲线,将软件部署到 docker 映像是否更容易?” . 我想你会发现答案总是“是”——但只有一种方法可以找到答案,在 Stack Overflow 上发布这个新问题。
有很多答案可以更详细地解释差异,但这是我非常简短的解释。
一个重要的区别是VM 使用单独的内核来运行操作系统。这就是它很重并且需要时间来启动,消耗更多系统资源的原因。
在 Docker 中,容器与主机共享内核;因此它重量轻,可以快速启动和停止。
在虚拟化中,资源是在设置开始时分配的,因此当虚拟机在很多时候处于空闲状态时,资源并没有得到充分利用。在 Docker 中,容器没有分配固定数量的硬件资源,可以根据需要自由使用资源,因此具有高度可扩展性。
Docker 使用UNION 文件系统.. Docker 使用写时复制技术来减少容器消耗的内存空间。在这里阅读更多
使用虚拟机,我们有一个服务器,我们在该服务器上有一个主机操作系统,然后我们有一个管理程序。然后在该虚拟机管理程序之上运行,我们拥有任意数量的客户操作系统,其中包含一个应用程序及其依赖的二进制文件,以及该服务器上的库。它带来了一个完整的客户操作系统。可以说是相当的重量级了。此外,您实际上可以在每台物理机器上放置多少也是有限制的。
另一方面,Docker 容器略有不同。我们有服务器。我们有主机操作系统。但在这种情况下,我们有Docker 引擎,而不是 hypervisor 。在这种情况下,我们不会带来整个客户操作系统。我们带来了一个非常薄的操作系统层,容器可以向下与主机操作系统对话,以便获得那里的内核功能。这使我们能够拥有一个非常轻量级的容器。
它所拥有的只是应用程序代码以及它需要的任何二进制文件和库。如果您希望它们也可以,这些二进制文件和库实际上可以在不同的容器之间共享。这使我们能够做的事情有很多。他们有更快的启动时间。你不能像那样在几秒钟内建立一个虚拟机。同样,尽快将它们降下来......所以我们可以非常快速地扩大和缩小规模,我们稍后会看到。
每个容器都认为它在自己的操作系统副本上运行。它有自己的文件系统、自己的注册表等,这是一种谎言。它实际上正在被虚拟化。
Source: Kubernetes in Action.
我在生产环境中使用过 Docker,并且非常多地使用过 Docker。当您习惯它时,您会发现它对于构建多容器和隔离环境非常强大。
Docker 是基于 LXC(Linux Container)开发的,并且可以在许多 Linux 发行版中完美运行,尤其是 Ubuntu。
Docker 容器是隔离的环境。top
当您在从 Docker 映像创建的 Docker 容器中发出命令时,您可以看到它。
除此之外,由于 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 和 Docker 实现了一个监控 kafka 的生态系统。
为此,我为 zookeeper、kafka、Prometheus、Grafana 和 jmx-collector 下载了已配置的 Docker 容器,然后使用 YAML 文件为其中一些安装了我自己的配置,或者对于其他一些,我更改了 Docker 容器中的一些文件和配置,然后我在单台机器上使用多容器 Docker 构建一个用于监控 kafka 的完整系统,具有隔离性、可扩展性和弹性,该架构可以轻松移动到多个服务器中。
除了 Docker Hub 站点之外,还有另一个名为 quay.io 的站点,您可以使用该站点在其中拥有自己的 Docker 映像仪表板,并从中拉/推。你甚至可以将 Docker 镜像从 Docker Hub 导入到 quay,然后在你自己的机器上从 quay 运行它们。
注意:一开始学习 Docker 看起来既复杂又困难,但是当你习惯了它之后,你就离不开它了。
我记得在使用 Docker 的第一天,我发出了错误的命令或错误地删除了我的容器以及所有数据和配置。
Docker是这样介绍自己的:
Docker 是推动容器运动的公司,也是唯一一家解决混合云中所有应用程序的容器平台提供商。当今的企业面临着数字化转型的压力,但受到现有应用程序和基础设施的限制,同时还要合理化日益多样化的云、数据中心和应用程序架构组合。Docker 实现了应用程序和基础设施以及开发人员和 IT 运营之间的真正独立性,以释放他们的潜力,并为更好的协作和创新创建模型。
所以Docker是基于容器的,这意味着你有可以在当前机器上运行的镜像和容器。它不包括像VM这样的操作系统,而是像一组不同的工作包,如 Java、Tomcat 等。
如果您了解容器,您就会了解 Docker 是什么以及它与VM的不同之处...
容器镜像是一个轻量级的、独立的、可执行的软件包,其中包括运行它所需的一切:代码、运行时、系统工具、系统库、设置。可用于基于 Linux 和 Windows 的应用程序,容器化软件将始终以相同的方式运行,无论环境如何。容器将软件与其周围环境隔离开来,例如开发和暂存环境之间的差异,并有助于减少在同一基础架构上运行不同软件的团队之间的冲突。
因此,如下图所示,每个容器都有一个单独的包,并在一台机器上运行,共享该机器的操作系统......它们安全且易于运输......
这里有很多很好的技术答案,清楚地讨论了 VM 和容器之间的差异以及 Docker 的起源。
对我而言,VM 和 Docker 之间的根本区别在于您如何管理应用程序的推广。
借助 VM,您可以将应用程序及其依赖项从一个 VM 提升到下一个 DEV,再到 UAT 再到 PRD。
使用 Docker 的想法是,您将应用程序及其所需的库捆绑在自己的容器中,然后将整个容器作为一个单元进行推广。
因此,在最基本的层面上,使用 VM 可以将应用程序及其依赖项作为离散组件进行推广,而使用 Docker 则可以一键推广所有内容。
是的,容器存在问题,包括管理它们,尽管 Kubernetes 或 Docker Swarm 等工具大大简化了任务。
Feature |
virtualization |
(Docker) Containers |
---|---|---|
操作系统 | 每个 VM 包含一个Guest OS |
每个 Docker 容器不包含Guest OS |
硬件 | 每个 VM 都包含操作系统运行所需的硬件的虚拟副本。 | 没有容器的硬件虚拟化 |
重量 | 虚拟机很重——原因在上面—— | 容器重量轻,因此速度快 |
所需软件 | 虚拟化使用称为管理程序的软件实现 | Containerzation 使用称为 Docker 的软件实现 |
核 | 虚拟机提供虚拟硬件(或可以安装操作系统和其他程序的硬件) | Docker 容器不使用任何硬件虚拟化。**有助于使用容器 |
抽象 | 虚拟机提供硬件抽象,因此您可以运行多个操作系统。 | 容器提供操作系统抽象,因此您可以运行多个容器。 |
开机时间 | 创建并需要大量资源开销需要很长时间(通常是几分钟),因为除了您要使用的软件之外,它们还运行整个操作系统。 | 因为在 Docker 容器中运行的程序直接与主机的 Linux 内核接口,所以花费的时间更少。 |
在我看来,这要看你的应用程序的需求,为什么决定部署到Docker,因为Docker根据其功能将应用程序分成小部分,这变得有效,因为当一个应用程序/功能出现错误时对其他应用没有影响,与使用完整的vm相比,它在配置上会更慢更复杂,但在某些方面比docker更安全
docker 文档(和不言自明)区分了“虚拟机”和“容器”。他们倾向于以不常见的方式解释和使用事物。他们可以这样做,因为这取决于他们,他们在文档中写了什么,并且因为虚拟化的术语还不是很准确。
事实上,Docker 文档对“容器”的理解是现实中的半虚拟化(有时是“OS 级虚拟化”),相反,硬件虚拟化不是 docker。
Docker 是一种低质量的半虚拟化解决方案。容器与 VM 的区别是由 docker 开发人员发明的,以解释其产品的严重缺点。
它之所以如此受欢迎,是因为他们“给普通人火了”,即它使典型的服务器(= Linux)环境/软件产品在Win10工作站上的简单使用成为可能。这也是我们容忍他们一点点“细微差别”的一个理由。但这并不意味着我们也应该相信它。
由于 Windows 主机上的 docker 在 HyperV 中使用嵌入式 Linux,并且它的容器已经在其中运行,因此情况变得更加模糊。因此,Windows 上的 docker 使用组合的硬件和半虚拟化解决方案。
简而言之,Docker 容器是低质量的(准)虚拟机,具有巨大的优势和许多劣势。