我一直在重读Docker文档,试图理解Docker和完整VM之间的区别。它是如何设法提供一个完整的文件系统、隔离的网络环境等而不那么沉重的?
为什么将软件部署到Docker映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
我一直在重读Docker文档,试图理解Docker和完整VM之间的区别。它是如何设法提供一个完整的文件系统、隔离的网络环境等而不那么沉重的?
为什么将软件部署到Docker映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
当前回答
有三种不同的设置提供了运行应用程序的堆栈(这将帮助我们认识到容器是什么,以及是什么使它比其他解决方案更强大):
1) Traditional Servers(bare metal)
2) Virtual machines (VMs)
3) Containers
1) 传统的服务器堆栈由运行操作系统和应用程序的物理服务器组成。
优势:
原始资源的利用隔离
缺点:
部署时间非常慢昂贵的浪费的资源难以扩展难以迁移复杂的配置
2) VM堆栈由运行操作系统的物理服务器和管理虚拟机、共享资源和网络接口的管理程序组成。每个Vm运行一个客户操作系统、一个应用程序或一组应用程序。
优势:
善用资源易于扩展易于备份和迁移成本效益灵活性
缺点:
资源分配有问题供应商锁定复杂的配置
3) 容器设置与其他堆栈的主要区别是基于容器的虚拟化使用主机操作系统的内核来管理多个孤立的来宾实例。这些来宾实例称为容器。主机可以是物理服务器或VM。
优势:
隔离轻量的资源有效易于迁移安全低开销镜像生产和开发环境
缺点:
相同的体系结构资源密集型应用网络和安全问题。
通过将容器设置与之前的设置进行比较,我们可以得出结论,容器化是迄今为止我们所知的最快、最有效的资源和最安全的设置。容器是运行应用程序的独立实例。Docker以某种方式旋转容器,层使用默认存储驱动程序(Overlay驱动程序)获得运行时内存,这些驱动程序在几秒钟内运行,一旦我们提交到容器中,就会在其上创建写时复制层,从而为容器的执行提供动力。如果是VM,则需要大约一分钟的时间将所有内容加载到虚拟化环境中。这些轻量级实例可以很容易地替换、重建和移动。这使我们能够镜像生产和开发环境,并在CI/CD过程中提供了巨大的帮助。容器所能提供的优势是如此引人注目,它们肯定会继续存在。
其他回答
我在生产环境和登台中使用过Docker。当你习惯了它,你会发现它对于构建一个多容器和隔离环境非常强大。
Docker是基于LXC(Linux容器)开发的,在许多Linux发行版中都能完美运行,尤其是Ubuntu。
Docker容器是隔离的环境。当您在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、PrometheusJMXExporter和Docker实现了一个用于监控kafka的生态系统。
为此,我为zookeeper、kafka、Prometheus、Grafana和jmx收集器下载了已配置的Docker容器,然后使用YAML文件为其中一些容器安装了自己的配置,我更改了Docker容器中的一些文件和配置,并在一台机器上使用多容器Docker构建了一个用于监控kafka的完整系统,该系统具有隔离性、可扩展性和弹性,该架构可以轻松移动到多个服务器中。
除了Docker Hub站点之外,还有一个名为quay.io的站点,您可以使用它在那里创建自己的Docker图像仪表板,并将其推送到码头。您甚至可以将Docker图像从DockerHub导入码头,然后在自己的机器上从码头运行。
注意:学习Docker一开始看起来既复杂又困难,但当你习惯了它之后,你就不能没有它了。
我记得在使用Docker的第一天,我发出了错误的命令,或者错误地删除了我的容器和所有数据和配置。
这里的大多数答案都涉及虚拟机。我将给你一个简单的回答,这个问题在过去几年中对我的帮助最大。是这样的:
Docker只是运行进程的一种奇特方式,而不是虚拟机。
现在,让我再解释一下这意味着什么。虚拟机是它们自己的野兽。我觉得解释Docker是什么比解释虚拟机更能帮助你理解这一点。特别是因为这里有很多很好的答案,告诉你某人说“虚拟机”的确切含义。所以
Docker容器只是一个进程(及其子进程),它使用主机系统内核内的cgroups与其他进程进行划分。通过在主机上运行ps aux,您实际上可以看到Docker容器进程。例如,“在容器中”启动apache2只是将apache2作为主机上的一个特殊进程启动。它只是与机器上的其他过程分开了。需要注意的是,容器不存在于容器化流程的生命周期之外。当你的进程失效时,你的容器也会失效。这是因为Docker将容器中的pid 1替换为应用程序(pid 1通常是init系统)。关于pid 1的最后一点非常重要。
就每个容器进程所使用的文件系统而言,Docker使用UnionFS支持的映像,这是您在Docker拉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进展很快。它的文档是我见过的最好的文档之一。它通常写得很好,简洁准确。我建议您查看可用的文档以获取更多信息,并将文档置于在线阅读的任何其他内容之上,包括堆栈溢出。如果你有具体的问题,我强烈建议加入Freenode IRC上的#docker并在那里提问(你甚至可以使用Freenode的网络聊天!)。
Docker最初使用LinuX Containers(LXC),但后来改用runC(以前称为libcontainer),后者与主机在同一操作系统中运行。这允许它共享大量主机操作系统资源。此外,它使用分层文件系统(AuFS)并管理网络。
AuFS是一个分层文件系统,因此可以将只读部分和写部分合并在一起。可以将操作系统的公共部分设置为只读(并在所有容器中共享),然后为每个容器提供自己的装载以供编写。
假设您有一个1GB的容器映像;如果要使用完整的虚拟机,则需要有1 GB x所需数量的虚拟机。使用Docker和AuFS,您可以在所有容器之间共享1GB的空间,如果您有1000个容器,那么容器操作系统的空间可能只有1GB多一点(假设它们都运行同一个操作系统映像)。
一个完整的虚拟化系统得到了它自己的一组资源分配,并且实现了最小的共享。你得到了更多的隔离,但它更重(需要更多的资源)。使用Docker可以减少隔离,但容器是轻量级的(需要更少的资源)。因此,您可以轻松地在主机上运行数千个容器,而且它甚至不会闪烁。试着用Xen做这件事,除非你有一个非常大的主机,否则我认为这是不可能的。
一个完整的虚拟化系统通常需要几分钟的启动时间,而Docker/LXC/runC容器需要几秒钟,甚至不到一秒钟。
每种类型的虚拟化系统都有利弊。如果您希望使用有保证的资源进行完全隔离,那么完整的VM是最佳选择。如果您只想将进程彼此隔离,并希望在一个大小合理的主机上运行大量进程,那么Docker/LXC/runC似乎是一个不错的选择。
有关更多信息,请查看这组博客文章,它们很好地解释了LXC的工作原理。
为什么将软件部署到docker映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
部署一致的生产环境说起来容易做起来难。即使您使用Chef和Puppet等工具,主机和环境之间也总是会有操作系统更新和其他变化。
Docker使您能够将操作系统快照到共享映像中,并使其易于在其他Docker主机上部署。本地、dev、qa、prod等:都是相同的图像。当然,你可以用其他工具来完成这项工作,但不是那么容易或快速。
这非常适合测试;假设您有数千个测试需要连接到数据库,每个测试都需要数据库的原始副本,并将对数据进行更改。经典的方法是在每次测试后使用自定义代码或使用Flyway等工具重置数据库-这可能非常耗时,意味着测试必须连续运行。然而,使用Docker,您可以创建数据库的映像,并为每个测试运行一个实例,然后并行运行所有测试,因为您知道它们都将针对数据库的同一快照运行。由于测试是在Docker容器中并行运行的,它们可以在同一时间在同一个盒子上运行,并且应该完成得更快。尝试使用完整的虚拟机执行此操作。
来自评论。。。
有趣的我想我仍然对“快照操作系统”的概念感到困惑。如果不制作操作系统的图像,那么如何做到这一点?
好吧,看看我能不能解释一下。您从一个基本图像开始,然后进行更改,并使用docker提交这些更改,然后创建一个图像。此图像仅包含与基础的差异。当你想运行你的镜像时,你也需要基础,它使用一个分层文件系统将你的镜像分层在基础之上:如上所述,Docker使用AuFS。AuFS将不同的层合并在一起,您可以得到所需的内容;你只需要运行它。你可以继续添加越来越多的图像(层),它将继续只保存差异。由于Docker通常基于注册表中的现成图像构建,因此您很少需要自己“快照”整个操作系统。
关于:-
“为什么将软件部署到docker映像比简单部署到一致的生产环境?"
大多数软件都部署到许多环境中,通常至少部署以下三种环境:
个人开发者PC共享开发人员环境单个测试仪PC共享测试环境QA环境UAT环境负载/性能测试实时登台生产档案文件
还需要考虑以下因素:
根据工作的性质,开发人员,甚至测试人员,都将拥有微妙的或完全不同的PC配置开发人员通常可以在公司或企业标准化规则无法控制的PC上进行开发(例如,在自己的机器上开发的自由职业者(通常是远程开发的),或未“受雇”或“签约”以某种方式配置其PC的开源项目的贡献者)某些环境将由负载平衡配置中的固定数量的多台计算机组成许多生产环境将根据流量级别动态(或“弹性”)创建和销毁基于云的服务器
正如你所看到的,一个组织的服务器总数很少是一位数,通常是三位数,而且很容易更高。
这一切都意味着,仅仅因为巨大的容量(即使是在绿地场景中),首先创建一致的环境就已经足够困难了,但鉴于服务器数量众多、新服务器的添加(动态或手动)、o/s供应商、防病毒供应商、浏览器供应商等的自动更新,由开发人员或服务器技术人员执行的手动软件安装或配置更改等。让我重复一遍-保持环境一致几乎是不可能的(没有双关语)(好吧,对于纯粹主义者来说,这是可以做到的,但这需要大量的时间、精力和纪律,这正是为什么VM和容器(例如Docker)最初被设计出来的原因)。
因此,请更像这样思考您的问题:“鉴于保持所有环境一致性的极端困难,即使考虑到学习曲线,将软件部署到docker映像中是否更容易?”。我想你会发现答案总是“是”——但只有一种方法可以找到,在Stack Overflow上发布这个新问题。
容器将库和软件包与系统隔离,以便您可以安装相同软件和库的不同版本而不发生冲突。它使用最小的存储空间和内存,使用相同的基本操作系统内核和可用的库几乎没有开销,如果可能的话,差异很小。您可以直接或间接地将硬件暴露给容器,以便可以使用加速(如gpu)进行计算。
在实践中,您可以使用预制容器的docker。您可以安装它们并在一条线上运行它们。安装tensorflow gpu和docker run-it tensorflow gpu一样简单。虽然我没有偶然发现许多lxd(lxc容器)的预制容器,但我发现它们更容易定制,更稳定和性能更好。
容器和VM都可以用来分配负载。但由于容器几乎没有开销,因此容器管理软件专注于创建容器集群,以便您轻松地将它们(从而将负载)分配给金属机器。
真实生活示例:
假设您需要50多种类型的计算环境和50种类型的服务,如mysql、网络托管和基于云的服务(如jenkins和对象存储),并且您有50多种不同的裸机服务器。这是一个典型的学院环境。您需要高效地使用资源,并且需要高可用性。当一台服务器停机时,用户应该不会遇到任何问题。为了解决这个问题,您所做的基本上是在所有服务器上安装所有类型的容器。并将负载分配给所有金属机器。当一种类型的容器需要更多时,可以在一台或多台裸机上自动生成更多容器。因此,许多不同的用户可以连续灵活地使用不同的服务和环境。
在该设置中,假设有100名学生同时使用该系统。其中95人使用服务器进行基本服务,如检查GPA、课程、图书馆数据库等,但其中5人正在进行5种不同类型的工程模拟。您将看到49台裸机服务器完全专用于工程仿真,每台服务器都有5种不同类型的计算容器,每种计算容器都与之相匹配,但与20%的硬件资源使用相平衡。当你为基本任务增加2500名学生时,这将使用所有裸机的5%。其余部分将用于计算。
因此,提供这种灵活性优势的容器最重要的区别特征是:
准备好部署预制容器,几乎没有开销,可快速繁殖具有实时可调整配额
使用.cpu_allowencess、.ram_allowances或直接cgroup。Kubernetes为您提供所有这些服务。在摆弄了docker和lxd之后,你可能想看看它。