Docker容器

容器、虚拟机和 Docker 的初学者友好介绍

本文主要是介绍容器、虚拟机和 Docker 的初学者友好介绍,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

如果您是一名程序员或技术人员,您可能至少听说过 Docker:一种用于在“容器”中打包、运输和运行应用程序的有用工具。 很难不这样做,因为这些天它受到了来自开发人员和系统管理员的所有关注。 甚至像谷歌、VMware 和亚马逊这样的巨头也在构建服务来支持它。

 

无论您是否有 Docker 的直接用例,我仍然认为了解有关“容器”是什么以及它与虚拟机 (VM) 的比较的一些基本概念很重要。 虽然互联网上到处都是 Docker 的优秀使用指南,但我找不到很多适合初学者的概念指南,尤其是关于容器的组成部分。 所以,希望这篇文章能解决这个问题:)

 

让我们从了解虚拟机和容器甚至是什么开始.

 

什么是“容器”和“虚拟机”?‍


容器和虚拟机的目标相似:将应用程序及其依赖项隔离到一个可以在任何地方运行的独立单元中。

 

此外,容器和虚拟机消除了对物理硬件的需求,允许更有效地使用计算资源,无论是在能源消耗还是成本效益方面。

 

容器和虚拟机之间的主要区别在于它们的架构方法。 让我们仔细看看。

 

虚拟机

 

虚拟机本质上是对真实计算机的仿真,它像真实计算机一样执行程序。 虚拟机运行在使用“管理程序”的物理机之上。 反过来,管理程序在主机或“裸机”上运行。

 

让我们拆开行话:

 

管理程序是虚拟机在其上运行的软件、固件或硬件。 管理程序本身在物理计算机上运行,称为“主机”。 主机为 VM 提供资源,包括 RAM 和 CPU。 这些资源在 VM 之间分配,并且可以根据您的需要进行分配。 因此,如果一个 VM 正在运行资源繁重的应用程序,那么您可能会为该应用程序分配比在同一主机上运行的其他 VM 多的资源。

 

在主机上运行的虚拟机(再次使用虚拟机管理程序)通常也称为“来宾机器”。 此来宾计算机包含应用程序以及运行该应用程序所需的任何内容(例如系统二进制文件和库)。 它还带有自己的完整虚拟化硬件堆栈,包括虚拟化网络适配器、存储和 CPU——这意味着它还拥有自己的成熟的客户操作系统。 从内部来看,来宾机器表现为自己的单元,拥有自己的专用资源。 从外面看,我们知道它是一个虚拟机——共享主机提供的资源。

 

如上所述,来宾机器可以在托管管理程序或裸机管理程序上运行。 它们之间有一些重要的区别。

 

首先,托管的虚拟化管理程序运行在主机的操作系统上。 例如,运行 OSX 的计算机可以在该操作系统之上安装 VM(例如 VirtualBox 或 VMware Workstation 8)。 VM 不能直接访问硬件,因此它必须通过主机操作系统(在我们的例子中是 Mac 的 OSX)。

 

托管管理程序的好处是底层硬件不太重要。 主机的操作系统负责硬件驱动程序而不是管理程序本身,因此被认为具有更多的“硬件兼容性”。 另一方面,硬件和管理程序之间的这个附加层会产生更多的资源开销,从而降低 VM 的性能。

 

裸机管理程序环境通过在主机硬件上安装和运行来解决性能问题。 因为它直接与底层硬件接口,所以它不需要运行主机操作系统。 在这种情况下,作为操作系统安装在主机服务器上的第一件事就是管理程序。 与托管管理程序不同,裸机管理程序有自己的设备驱动程序,并直接与每个组件交互以执行任何 I/O、处理或特定于操作系统的任务。 这会带来更好的性能、可扩展性和稳定性。 这里的权衡是硬件兼容性是有限的,因为虚拟机管理程序只能内置这么多设备驱动程序。

 

在讨论了管理程序之后,您可能想知道为什么我们需要在 VM 和主机之间添加这个额外的“管理程序”层。

 

好吧,由于 VM 有自己的虚拟操作系统,因此管理程序在为 VM 提供管理和执行此客户操作系统的平台方面发挥着重要作用。 它允许主机在作为来宾运行的虚拟机之间共享其资源。

 

正如您在图中所见,VM 为每个新 VM 打包了虚拟硬件、内核(即操作系统)和用户空间。

 

容器

 

与提供硬件虚拟化的 VM 不同,容器通过抽象“用户空间”来提供操作系统级别的虚拟化。 当我们打开术语容器时,您会明白我的意思。

 

出于所有意图和目的,容器看起来像一个虚拟机。 例如,它们具有用于处理的私有空间,可以以 root 身份执行命令,具有私有网络接口和 IP 地址,允许自定义路由和 iptable 规则,可以挂载文件系统等。

 

容器和虚拟机之间的一大区别是容器与其他容器*共享*主机系统的内核。

 

该图向您展示了容器只打包了用户空间,而不是像 VM 那样打包内核或虚拟硬件。 每个容器都有自己独立的用户空间,以允许多个容器在单个主机上运行。 我们可以看到所有操作系统级架构都在容器之间共享。 从头开始创建的唯一部分是 bins 和 libs。 这就是容器如此轻量级的原因。


Docker 从何而来?
Docker 是一个基于 Linux 容器的开源项目。 它使用 Linux 内核功能(如命名空间和控制组)在操作系统之上创建容器。

容器远非新鲜事物; 谷歌多年来一直在使用自己的容器技术。 其他 Linux 容器技术包括已经存在多年的 Solaris Zones、BSD jails 和 LXC。

 

那么为什么 Docker 会突然变得火爆呢?

 

1. 易用性:Docker 使任何人(开发人员、系统管理员、架构师和其他人)都可以更轻松地利用容器来快速构建和测试可移植应用程序。 它允许任何人在他们的笔记本电脑上打包应用程序,而后者可以在任何公共云、私有云甚至裸机上未经修改地运行。 口头禅是:“一次构建,随处运行。”

 

2. 速度:Docker 容器非常轻量和快速。 由于容器只是在内核上运行的沙盒环境,因此它们占用的资源更少。 您可以在几秒钟内创建和运行 Docker 容器,而 VM 可能需要更长的时间,因为它们每次都必须启动完整的虚拟操作系统。

 

3. Docker Hub:Docker 用户还受益于 Docker Hub 日益丰富的生态系统,您可以将其视为“Docker 镜像的应用程序商店”。 Docker Hub 拥有数以万计由社区创建的公共镜像,可供随时使用。 搜索满足您需求的图像非常容易,只需很少或无需修改即可下拉和使用。

 

4. 模块化和可扩展性:Docker 可以轻松地将应用程序的功能分解为单个容器。 例如,您可能将 Postgres 数据库运行在一个容器中,将 Redis 服务器运行在另一个容器中,而您的 Node.js 应用程序在另一个容器中。 使用 Docker,将这些容器链接在一起以创建应用程序变得更加容易,从而可以轻松地在未来独立扩展或更新组件。

 

最后但并非最不重要的一点是,谁不喜欢 Docker ?

 

基本的 Docker 概念


现在我们已经有了大局,让我们一点一点地了解 Docker 的基本部分:

 

Docker 引擎

 

Docker 引擎是运行 Docker 的层。 它是一个轻量级的运行时和工具,用于管理容器、图像、构建等。 它在 Linux 系统上本地运行,由以下部分组成:

 

1. 一个运行在主机上的Docker Daemon。

 

2. Docker 客户端,然后与 Docker 守护程序通信以执行命令。

 

3. 用于与 Docker Daemon 远程交互的 REST API。

 

Docker 客户端

 

Docker 客户端是您作为 Docker 的最终用户与之通信的对象。 将其视为 Docker 的 UI。 例如,当你做...

 

您正在与 Docker 客户端通信,然后客户端将您的指令传达给 Docker 守护程序。

 

Docker 守护进程

 

Docker 守护进程实际执行发送到 Docker 客户端的命令——比如构建、运行和分发你的容器。 Docker Daemon 在主机上运行,但作为用户,您永远不会直接与 Daemon 通信。 Docker 客户端也可以在主机上运行,但不是必需的。 它可以运行在不同的机器上,并与运行在主机上的 Docker 守护进程通信。

 

文件

 

Dockerfile 是您编写构建 Docker 镜像的指令的地方。 这些说明可以是:

 

RUN apt-get y install some-package:安装一个软件包

 

EXPOSE 8000:暴露端口

 

ENV ANT_HOME /usr/local/apache-ant 传递环境变量

 

等等。 设置好 Dockerfile 后,您可以使用 docker build 命令从中构建映像。 下面是一个 Dockerfile 的例子:

 

Docker 镜像

 

图像是只读模板,您根据 Dockerfile 中编写的一组指令构建。 图像定义了您希望打包的应用程序及其依赖项的外观*和*启动时要运行的进程。

 

Docker 镜像是使用 Dockerfile 构建的。 Dockerfile 中的每条指令都会向镜像添加一个新的“层”,层代表镜像文件系统的一部分,该部分添加到或替换其下方的层。 层是 Docker 轻量级但功能强大的结构的关键。 Docker 使用联合文件系统来实现这一点:

 

联合文件系统

 

Docker 使用联合文件系统来构建镜像。 您可以将联合文件系统视为可堆叠的文件系统,这意味着独立文件系统(称为分支)的文件和目录可以透明地重叠以形成单个文件系统。

 

在重叠分支中具有相同路径的目录的内容被视为单个合并目录,这避免了为每一层创建单独副本的需要。 相反,它们都可以被赋予指向相同资源的指针; 当某些图层需要修改时,它会创建一个副本并修改一个本地副本,保持原来的不变。 这就是文件系统如何*看起来*可写而实际上不允许写入。 (换句话说,一个“写时复制”系统。)

 

分层系统提供两个主要好处:

 

1. 无重复:每次使用镜像创建和运行新容器时,层有助于避免复制完整的文件集,从而使 docker 容器的实例化非常快速且廉价。

 

2. 层隔离:进行更改的速度要快得多——当您更改映像时,Docker 只会将更新传播到已更改的层。

 

 

卷是容器的“数据”部分,在创建容器时初始化。 卷允许您持久化和共享容器的数据。 数据卷独立于默认的联合文件系统,并作为主机文件系统上的普通目录和文件存在。 因此,即使您销毁、更新或重建您的容器,数据卷也将保持不变。 当您想要更新卷时,您可以直接对其进行更改。 (作为一个额外的好处,数据卷可以在多个容器之间共享和重用,这非常简洁。)

 

Docker 容器

 

如上所述,Docker 容器将应用程序的软件包装到一个不可见的盒子中,其中包含应用程序运行所需的一切。 这包括操作系统、应用程序代码、运行时、系统工具、系统库等。Docker 容器是基于 Docker 镜像构建的。 由于镜像是只读的,Docker 在镜像的只读文件系统之上增加了一个可读写的文件系统来创建一个容器。

 

 

此外,在创建容器之后,Docker 会创建一个网络接口,以便容器可以与本地主机通信,将可用 IP 地址附加到容器,并执行您在定义映像时指定的运行应用程序的进程。

 

成功创建容器后,您就可以在任何环境中运行它,而无需进行任何更改。

 

双击“容器”

 

呼! 这是很多活动部件。 一直让我好奇的一件事是容器是如何实际实现的,尤其是因为容器周围没有任何抽象的基础设施边界。 经过大量阅读,这一切都说得通,所以这是我向您解释的尝试! :)

 

术语“容器”实际上只是一个抽象概念,用于描述几个不同的功能如何协同工作以可视化“容器”。 让我们快速浏览它们:

 

1) 命名空间

 

命名空间为容器提供了自己的底层 Linux 系统视图,限制了容器可以看到和访问的内容。 当您运行容器时,Docker 会创建特定容器将使用的命名空间。

 

Docker 使用的内核中有几种不同类型的命名空间,例如:

 

一种。 NET:为容器提供自己的系统网络堆栈视图(例如,它自己的网络设备、IP 地址、IP 路由表、/proc/net 目录、端口号等)。

 

湾 PID:PID 代表进程 ID。 如果您曾经在命令行中运行 ps aux 来检查系统上正在运行哪些进程,您将会看到名为“PID”的列。 PID 命名空间为容器提供了自己可以查看和交互的进程的范围视图,包括一个独立的 init (PID 1),它是“所有进程的祖先”。

 

C。 MNT:为容器提供自己的系统“挂载”视图。 因此,不同挂载命名空间中的进程对文件系统层次结构有不同的看法。

 

d. UTS:UTS 代表 UNIX 分时系统。 它允许进程识别系统标识符(即主机名、域名等)。 UTS 允许容器拥有自己的主机名和 NIS 域名,独立于其他容器和主机系统。

 

e. IPC:IPC 代表进程间通信。 IPC 命名空间负责在每个容器内运行的进程之间隔离 IPC 资源。

 

F。 USER:这个命名空间用于隔离每个容器内的用户。 与主机系统相比,它通过允许容器具有不同的 uid(用户 ID)和 gid(组 ID)范围视图来发挥作用。 因此,进程的 uid 和 gid 在用户命名空间内外可以不同,这也允许进程在容器外拥有非特权用户,而不会牺牲容器内的 root 权限。

 

Docker 一起使用这些命名空间以隔离并开始创建容器。 下一个功能称为控制组。

 

2) 对照组

 

控制组(也称为 cgroups)是 Linux 内核的一项功能,可隔离、确定优先级并说明一组进程的资源使用情况(CPU、内存、磁盘 I/O、网络等)。 从这个意义上说,cgroup 确保 Docker 容器只使用它们需要的资源——并且,如果需要,设置容器*可以*使用的资源的限制。 Cgroups 还确保单个容器不会耗尽其中一个资源并使整个系统停机。

 

最后,联合文件系统是 Docker 使用的另一个功能:

 

3) 隔离联合文件系统:

 

上面在 Docker 图像部分中描述了 :)

 

这就是 Docker 容器的全部内容(当然,问题在于实现细节——比如如何管理各种组件之间的交互)。

 

Docker 的未来:Docker 和 VM 将共存

 

虽然 Docker 确实获得了很大的发展,但我认为它不会成为对虚拟机的真正威胁。 容器将继续取得进展,但在许多用例中,VM 仍然更适合。

 

例如,如果您需要在多台服务器上运行多个应用程序,那么使用 VM 可能是有意义的。 另一方面,如果您需要运行单个应用程序的多个*副本*,Docker 提供了一些引人注目的优势。

 

此外,虽然容器允许您将应用程序分解为更多功能的离散部分以创建关注点分离,但这也意味着需要管理的部分越来越多,这可能会变得笨拙。

 

安全性也是 Docker 容器关注的一个领域——由于容器共享相同的内核,容器之间的屏障更薄。 虽然完整的 VM 只能向主机管理程序发出超级调用,但 Docker 容器可以向主机内核发出系统调用,这为攻击创造了更大的表面积。 当安全性特别重要时,开发人员可能会选择由抽象硬件隔离的虚拟机——这使得相互干扰变得更加困难。

 

当然,随着容器在生产中得到更多的曝光和来自用户的进一步审查,安全和管理等问题肯定会发展。 目前,关于容器与虚拟机的争论真的最适合每天生活和呼吸它们的开发运营人员!

 

结论

 

我希望您现在已经掌握了了解 Docker 所需的知识,甚至有一天可能会在项目中使用它。

 

这篇关于容器、虚拟机和 Docker 的初学者友好介绍的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!