Podman实战

978-7-115-63806-9
作者: 丹尼尔·沃尔什(Daniel Walsh)
译者: 杨少鹏曲志兵
编辑: 佘洁
分类:

图书目录:

详情

本书主要介绍了如何构建、管理和运行容器,解释如何将人们在Docker中学到的技能轻松地转移到Podman上,以及如果你以前从未使用过容器引擎,你该如何轻松地学习使用Podman。本书还教你使用像pod这样的高级功能,并指导你构建准备在Kubernetes边缘或内部运行的应用程序。最后,本书解释了Linux内核中用于将容器与系统和其他容器进行隔离的所有安全功能。 本书适用于希望了解、开发和使用容器的软件开发人员,以及需要在生产环境中运行容器的系统管理员。Docker用户也能通过本书了解一些Docker没有提供的Podman高级功能,并会对Docker的工作原理有更深入的理解。

图书摘要

版权信息

书名:Podman实战

ISBN:978-7-115-63806-9

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

版  权

著    [美]丹尼尔·沃尔什(Daniel Walsh)

译    杨少鹏 曲志兵

责任编辑 佘 洁

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315

内容提要

本书主要介绍了如何构建、管理和运行容器,讲解了如何将人们在Docker中学到的技能轻松地转移到Podman上,即使你从未使用过容器引擎,也可以通过本书轻松地学习使用Podman。本书还将教会你使用像pod这样的高级功能,并指导你构建准备在Kubernetes边缘或内部运行的应用程序。最后,本书介绍了Linux内核中用于将容器与系统及其他容器进行隔离的所有安全功能方面的知识。

本书适用于希望了解、开发和使用容器的软件开发人员,以及需要在生产环境中运行容器的系统管理员。Docker用户也能通过本书了解一些Docker没有提供的Podman高级功能,并对Docker的工作原理有更深入的理解。

译者介绍

杨少鹏,复旦大学计算机科学技术学院硕士毕业生,现就职于一家知名跨国互联网公司。他在应用平台和容器平台开发领域有着深厚的专业背景,精通Docker、Kubernetes等主流容器技术,并在实践中积累了丰富的开发经验。

曲志兵,担任某国际企业技术专家,拥有8年丰富的技术开发背景。他曾在国内顶尖互联网公司任职,专注于PaaS平台开发,对PaaS平台的构建及其基础设施的稳定性保障有着丰富的实战经验和深入的理解。

前  言

我已经从事计算机安全工作近40年了,在过去的20年里,我一直专注于容器技术。大约10年前出现的Docker,掀起了一场有关人们如何在互联网上分发和运行应用程序的革命。当开始使用Docker时,我感觉它的设计还可以更好。使用一个以root(特权)身份运行的守护进程,然后不断添加更多的守护进程,我认为这不是正确的做法。我觉得可以利用底层操作系统的概念来创建一个以更高安全性和更少特权来运行相同容器化应用程序的工具。基于这个想法,我在Red Hat公司时的团队开始构建一系列工具,以帮助开发人员和管理员以更安全的方式来运行容器,而Podman就是这一系列工具之一。

我从2000年年初开始撰写关于SELinux等主题的博客,至今已经写了大量文章。这些年,我撰写了数百篇有关容器和安全性的文章,我希望能够将这些想法整合起来,写一本介绍Podman技术的书,以供用户和客户参考。

本书介绍了Podman及其使用方法,并深入探讨了我们用到的Linux操作系统的不同功能和技术。作为一名安全工程师,我还用几章的篇幅描述了容器安全的工作原理。阅读本书应该能让你更好地了解容器是什么、它们如何工作,以及如何使用Podman的不同功能。你甚至会了解更多关于Docker的知识。随着Podman日益普及并逐步应用到更多系统的基础架构中,本书将成为一个引导你前行的、便捷的Podman实践参考指南。

致谢

我要感谢所有帮助我完成本书撰写的人。首先感谢Podman团队的成员,他们撰写的许多技术文章帮助我理解了一些我此前没有完全理解的技术,并帮助构建了Podman这个伟大的产品,他们是Brent Baude、Matt Heon、Valentin Rothberg、Giuseppe Scrivano、Urvashi Mohnani、Nalin Dahyabhai、Lokesh Mandvekar、Miloslav Trmac、Jason Greene、Jhon Honce、Scott McCarty、Tom Sweeney、Ashley Cui、Ed Santiago、Chris Evich、Aditya Rajan、Paul Holzinger、Preethi Thomas和Charlie Doern。我还要感谢无数的开源贡献者,是他们使Linux容器和Podman成为可能。

我也要感谢Manning的整个团队,尤其是Toni Arritola。Toni教会了我如何更好地聚焦我的想法。在完成此书的过程中,她是我非常棒的合作伙伴,正是她的帮助才使本书圆满完成。

感谢所有的审稿人——Alain Lompo、Alessandro Campeis、Allan Makura、Amanda Debler、Anders Björklund、Andrea Monacchi、Camal Cakar、Clifford Thurber、Conor Redmond、David Paccoud、Deepak Sharma、Federico Kircheis、Frans Oilinki、Gowtham Sadasivam、Ibrahim Akkulak、James Liu、James Nyika、Jeremy Chen、Kent Spillner、Kevin Etienne、Kirill Shirinkin、Kosmas Chatzimichalis、Krzysztof Kamyczek、Larry Cai、Michael Bright、Mladen Knežić、Oliver Korten、Richard Meinsen、Roman Zhuzha、Rui Liu、Satadru Roy、Seung-jin Kim、Simeon Leyzerzon、Simone Sguazza、Syed Ahmed、Thomas Peklak和Vivek Veerappan,感谢你们,你们的修改建议让本书变得更好。

关于本书

本书主要介绍了如何构建、管理和运行容器,写作目标是阐述如何将人们在Docker中学到的技能轻松地转移到Podman上,以及如果你从未使用过容器引擎,应该如何轻松地学习使用Podman。本书还将教会你使用像pod这样的高级功能,并指导你构建准备在Kubernetes边缘或内部运行的应用程序。最后,本书介绍了Linux内核中用于将容器与系统及其他容器进行隔离的所有安全功能。

本书的目标读者

本书适用于希望了解、开发和使用容器的软件开发人员,以及需要在生产环境中运行容器的系统管理员。阅读本书将让你更深入地理解容器是什么。具备Linux进程相关知识且熟悉Linux Shell的用法对于充分理解本书很有必要。

对所有探索容器使用方法的人来说,阅读本书都会有所收获。对Docker有深刻理解的用户也会从书中了解到一些Docker不提供而Podman拥有的高级功能,并会对Docker的工作原理有更深入的理解。初学者还将学到容器和pod的相关基础知识。

本书的组织结构

本书包括4部分和6个附录。

第1部分“基础”,包括4章,介绍了Podman的基础内容。第1章解释了Podman的功能、Podman项目的发起原因以及为什么它很重要。接下来的两章介绍Podman命令行界面和如何在容器内使用卷。第4章介绍pod的概念以及如何在Podman中使用pod。这些章节适合各种水平的读者阅读,但如果你在Docker方面拥有丰富的实践经验,则可以快速浏览第2章的大部分内容。

第2部分“设计”,包括两章,深入探讨了Podman的设计。在这部分,你将了解非特权容器及其工作原理,更好地理解用户命名空间和非特权容器的安全性,以及学习如何自定义Podman的环境配置。

第3部分“高级主题”,包括3章,内容超越了Podman的基础知识。在第7章中,你将了解到通过与systemd集成,Podman如何在生产环境中运行。它涵盖了在容器内运行systemd以及如何将其用作容器管理器等内容。你将学习如何使用Podman和systemd在边缘设备上管理容器化服务的生命周期。Podman使得生成systemd单元文件变得简单,从而帮助你将容器化应用程序更快地投入生产环境。在第8章中,你将了解到如何使用Podman将容器迁移到Kubernetes中。Podman支持使用与Kubernetes相同的YAML文件来启动容器,并能够从当前容器生成Kubernetes YAML。在第9章中,你将看到Podman可以作为服务运行,从而允许远程访问Podman容器。基于Podman服务,你可以使用其他编程语言和工具来管理Podman容器。你还将了解到docker-compose如何与Podman容器配合使用,以及学习如何使用Python库(如podman-py和docker-py)与Podman服务通信,以达到管理容器的目的。

第4部分“容器安全”,包括两章,讨论重要的安全注意事项。第10章介绍确保容器隔离的功能。该章涵盖了Linux的安全子系统,如SELinux、seccomp、Linux能力、内核文件系统和命名空间。随后的第11章详细讨论了一些安全注意事项。我认为,如果要以尽可能安全的方式运行容器,则可以将这些安全注意事项当作最佳实践。

此外,6个附录涵盖了与Podman相关的主题。

附录A介绍了与Podman相关的工具,包括Skopeo、Buildah和CRI-O。

附录B深入介绍了Podman和Docker中可用的各种OCI运行时,包括runc、crun、Kata和gVisor。

附录C描述了如何将Podman安装到本地系统,无论该系统是Linux、macOS还是Windows。

附录D介绍了Podman开源社区以及如何加入社区。

附录E和F分别深入介绍了在使用macOS和Windows系统的机器上运行Podman的方法。

关于作者

丹尼尔·沃尔什(Daniel Walsh)领导了创建Podman、Buildah、Skopeo、CRI-O及其相关工具的团队。他是Red Hat公司的杰出高级工程师,于2001年8月加入该公司。他在计算机安全领域工作了40多年。在领导容器团队之前,他曾在Red Hat公司领导SELinux的开发,因此有时被称为“SELinux先生”。他拥有圣十字学院(College of the Holy Cross)的数学学士学位和伍斯特理工学院(Worcester Polytechnic Institute)的计算机科学硕士学位。你可以在GitHub上找到他的账号(@rhatdan),也可以通过电子邮件联系他,他的邮箱为dwalsh@redhat.com。

关于封面插图

本书封面上的插图被称为“La Vandale”,意为“破坏者”,它来自Jacques Grasset de Saint-Sauveur于1797年出版的一本作品集(其中的每个插图都是手工精心绘制和上色的)。在那个时代,人们可以通过服饰轻松地辨别一个人的居住地、职业和社会地位。本书的封面来自这本作品集中的图片,以此颂扬计算机行业的创新和进取精神。

第1部分 基础

 在本书的第1部分,我将向你介绍几种通过命令行使用Podman的方法。在第2章中,你将了解如何创建和使用容器、容器如何与镜像一起工作、容器和镜像之间的区别,以及如何将容器保存为容器镜像,然后将镜像推送到容器镜像注册服务器,以便与其他用户共享。第1部分的前两章集中介绍容器和镜像的用法,它们与Docker中容器的工作方式非常相似。

第3章介绍了“卷”的概念。卷是大多数容器化应用程序的用户用于存储数据并将其与应用程序隔离的机制。

第4章引入了pod的概念,类似于Kubernetes中的pod。Docker不支持这一特性。pod允许你在同一资源、命名空间和安全约束内共享一个或多个容器。pod可以让你编写更复杂的应用程序,并将其作为单一实体进行管理。

第1章 Podman:下一代容器引擎

本章内容:

Podman是什么

与Docker相比,Podman有什么优势

Podman的使用示例

写作这本书是不容易的,因为很多人带着不同的期望和经验来阅读它。你可能已经拥有一些关于容器、Docker或Kubernetes的经验,或者至少对学习更多关于Podman的知识感兴趣,因为你已经听说过它。如果你之前使用或者了解过Docker,会发现在大多数情况下Podman和Docker的工作方式是一样的,但是Podman解决了一些Docker一直存在的问题。其中最重要的两点是,Podman提供了增强的安全性和以非root权限执行命令的能力。这意味着你可以在没有root访问权限(或特权)的情况下使用Podman来管理容器。Podman的设计使其在默认情况下比Docker具有更好的安全性。

Podman和Docker都是开源的(也是免费的)。除此之外,Podman通过命令行界面(CLI)执行的命令与Docker也非常相似。本书将向你讲述如何在单节点上使用Podman作为本地容器引擎来启动容器,你可以在本地启动容器,也可以通过远程的REST API来启动容器。同时,本书也将向你展示如何使用Podman与Buildah、Skopeo这样的开源工具来发现、运行和构建容器。

1.1 术语说明

在正式学习之前,我认为首先定义本书中要用到的术语很重要。在容器领域,像容器编排器、容器引擎和容器运行时这样的术语经常被交替使用,这通常会导致概念混淆。以下是本书对这些术语的总结。

容器编排器:指将容器分配到多个不同的机器或者节点上的软件项目或产品。编排器通过与容器引擎通信来运行容器。当前主要的容器编排器是Kubernetes,最初它被设计用来与Docker守护进程交互,但是由于Kubernetes主要使用CRI-O或containerd作为其容器引擎,因此Docker正在被逐步淘汰。CRI-O和containerd是专为Kubernetes编排和运行容器而构建的(CRI-O将在附录A中介绍)。此外,还有Docker Swarm和Apache MESOS等其他容器编排器。

容器引擎:最初被用来实现将容器化应用程序配置在单个本地节点上运行。普通用户、管理员和开发人员都可以直接启动容器引擎。容器引擎可以作为systemd的一个启动项被启动,也可以通过Kubernetes等容器编排器启动。上文提到CRI-O和containerd这两种容器引擎被Kubernetes用来管理本地容器,实际上这两种容器引擎并不打算让普通用户直接使用。Docker和Podman则是被普通用户用来在单台机器上开发、管理和运行容器化应用程序的两种主要的容器引擎。Podman很少会被用在Kubernetes中启动容器,因此,本书中也不会过多介绍Kubernetes相关的知识。Buildah是另外一种容器引擎,仅用于构建容器镜像。

OCI(开放容器计划)容器运行时:它负责完成Linux内核参数的配置,并最终启动容器化应用程序。最常用的两种容器运行时是runc和crun。Kata和gVisor是另外两种容器运行时。附录B将对各种OCI容器运行时的差异进行说明。

图1-1展示了开源容器项目从属的类别。

图1-1 按编排器、引擎和运行时对不同容器开源项目进行分类

Podman是pod manager的缩写。pod是Kubernetes项目中普遍存在的一个概念。一个pod可以有一个或多个容器,这些容器共享相同的命名空间和控制组(cgroups,用于资源约束)。第4章会更深入地介绍pod。Podman可以用来运行单个容器或者pod。Podman的Logo是一组海豹,如图1-2所示。该图案源自爱尔兰人概念里的美人鱼形象。一组海豹就形成了逻辑概念上的pod。

图1-2 Podman的Logo

Podman项目将Podman描述为“用于在Linux系统上开发、管理和运行OCI容器的无守护进程的容器引擎。容器既可以以特权模式运行,也可以以非特权模式运行”。Podman通常用简单的一行“alias docker=podman”来描述,因为Podman可以使用与Docker相同的命令行来完成Docker所能做的几乎所有事情。但正如你在本书中了解的那样,Podman可以做的还远不止这些。理解Docker对于理解Podman并不是必须的,但会很有帮助。

提示 开放容器计划(Open Container Initiative,OCI)是一个标准化组织,其主要目标是围绕容器格式和运行时建立开放的行业标准。可以通过访问https://opencontainers.org了解更多信息。

Podman的上游项目位于github.com上的Containers项目中,如图1-3所示。在该网页上还包括其他容器库和容器管理工具,如Buildah和Skopeo(有关这些工具的说明,参见附录A)。

如1.2.1节中所描述的那样,Podman支持新的OCI格式的镜像,同时也支持旧的Docker(V2和V1)格式的镜像。Podman可以运行来自诸如docker.io和quay.io等容器镜像注册服务器中的任何镜像,还支持数百个其他容器镜像注册服务器。Podman将这些镜像拉到Linux主机上,然后会以与Docker和Kubernetes类似的方式启动这些镜像。同Docker一样,Podman支持所有类型的OCI运行时,包括runc、crun、Kata和gVisor(见附录B)。

本书旨在帮助Linux管理员了解将Podman用作主要容器引擎的好处。你可以通过本书了解如何在尽可能确保系统配置安全的同时,允许普通用户使用容器。Podman最主要的一个使用场景是在诸如边缘设备这样的单节点环境上运行容器化应用程序。Podman和systemd一起使用可以实现在无须人工干预的情况下管理节点上应用程序的整个生命周期。Podman的目标是可以在Linux上自然地运行容器,从而充分利用Linux平台的所有功能。

提示 可以将Podman安装在Linux的多种发行版以及macOS和Windows平台上。如果你想进一步了解如何在你的平台上获取Podman,请参阅附录C。

图1-3 Containers是Podman和其他相关容器工具的开发者站点

应用程序开发者也是本书的目标读者。对开发者来说,Podman是一种以安全方式实现容器化应用程序的很好的工具。Podman允许开发者在所有Linux发行版中创建Linux容器。此外,Podman也可以在macOS和Windows平台上使用。在这些平台上,它可以通过网络与运行在虚拟机或者Linux机器上的Podman服务进行通信。本书将向你介绍如何使用容器、构建容器镜像,然后将容器化应用程序转换成在边缘设备上运行的单节点服务或者基于Kubernetes的微服务。

Podman和其他一些容器工具都是开源项目,这些项目的贡献者来自全世界不同的公司、大学和组织。当然,这些开源项目也欢迎新的贡献者来优化和改进。要了解有关如何加入这个项目的信息,可以参阅附录D。本章首先简要概述一下容器,然后介绍使Podman成为容器领域非常好的工具的一些核心功能。

1.2 容器简介

容器是在Linux系统上运行的一组进程,它们相互隔离。容器确保一个进程组不会干扰系统上的其他进程。恶意进程不能支配系统资源,否则会阻止其他进程任务的顺利执行。我们也要防止恶意容器攻击其他容器、窃取数据或造成拒绝服务攻击。容器的最终目标是允许应用程序安装它们自己版本的共享库,而不会与需要不同版本的相同库的应用程序发生冲突。相反,它们允许应用程序运行在虚拟化环境中,从而使得容器化环境中的应用程序看上去拥有了整个系统。

容器通过以下方式进行隔离。

1.资源限制(cgroups)

cgroups在手册页(https://man7.org/linux/man-pages/man7/cgroups.7.html)上被定义为控制组(Control Groups),通常被称为cgroups,是Linux内核的一项功能,它允许将进程组织成分层的组,并对这些分层的组实现多种类型的资源限制和监控。

cgroups控制的资源实例如下。

一组进程可以使用的内存量。

进程可使用的CPU核数。

进程可使用的网络资源数量。

cgroups的基本思想是防止一组进程独占某些系统资源,使得其他进程无法使用。

2.安全限制

内核中的很多安全工具可以实现容器间的相互隔离。安全限制的目标是限制特权升级,并防止一组流氓进程对系统实施破坏性行为,比如:

通过放弃一些Linux能力来限制root用户的权限。

通过SELinux控制对文件系统的访问。

只读访问内核文件系统。

通过seccomp限制内核中可用的系统调用。

通过用户命名空间将主机上的一组UID映射到另一组UID,从而允许访问有限的特权环境。

表1-1提供了进一步的信息和链接,可以通过这些链接获取有关这些安全功能的更多细节。

表1-1 高级Linux安全功能

组件

描述

参考资料

Linux能力

Linux能力将root权限细分为不同的能力

能力的手册页很好地概述了可用的能力。可以通过执行命令man capabilities或者通过https://bit.ly/3A3Ppeg查看

SELinux

Security Enhanced Linux (SELinux)是一种Linux内核机制,它标记系统上的每个进程和每个文件系统对象。SELinux策略定义了关于标签进程如何与标签对象交互的规则。Linux内核强制执行这些规则

笔者撰写的“SELinux Coloring Book”(https://bit.ly/33plEbD)可以帮助你更好地理解SELinux

如果你真的想研究SELinux,可以参考“SELinux笔记”(https://bit.ly/3GxGhkm)

seccomp

seccomp是一种Linux内核机制,可以用于限制系统上一组进程的系统调用数量。你可以从中删除具有潜在危险的系统调用

seccomp的手册页有关于seccomp的更多信息。可以通过执行命令man seccomp或者通过https://bit.ly/3rnnim1查看

用户命名空间

用户命名空间允许你在分配给命名空间的UID和GID组内拥有Linux能力,而无须在主机上拥有root权限

用户命名空间将在第3章进行详细介绍

3.虚拟化技术(命名空间)

Linux内核使用命名空间来创建一个虚拟化环境。在这个虚拟化环境中,一组进程看到的是一组资源,另一组进程则看到的是另一组不同的资源。这些虚拟化环境使进程无法看到系统的其他部分,感觉像一个虚拟机(VM),且没有额外的系统开销。下面给出命名空间的若干示例。

网络命名空间:限制对主机网络的访问,但是提供了对虚拟网络设备的访问。

挂载命名空间:限制只能看到容器文件系统,而不能看到所有的文件系统。

PID命名空间:限制容器进程只能看到容器内的进程,而看不到系统上的其他进程。

这些容器技术在Linux内核中已经存在很多年了。用于隔离进程的安全工具始于20世纪70年代的UNIX,而SELinux在2001年就已经存在。命名空间和控制组功能分别在2004年和2006年被引入。

提示 Windows容器镜像也是存在的,但是本书主要关注的是基于Linux的容器。即使在Windows上运行Podman,实际上使用的还是Linux容器。在macOS上使用Podman的方法可以参阅附录E。在Windows上使用Podman的方法可以参阅附录F。

1.2.1 容器镜像:软件交付的新方式

直到Docker项目引入了容器镜像和容器镜像注册服务器等概念,容器技术才真正开始被广泛使用。可以这么说,它们创造了一种新的软件交付方式。

传统的在Linux系统上安装多个软件应用程序可能会导致依赖管理问题。在容器出现之前,可以使用像RPM和Debian Packages这样的软件包管理器来打包软件。这些软件包安装在主机上,并且共享包括共享库在内的所有内容。当开发者团队测试他们的代码时,在主机上运行时可能一切都正常。而当质量工程师团队在不同的机器上用不同的软件包测试软件时,就可能遭遇失败。两个团队需要一起努力才能达成期望的效果。软件最终交付给客户,这些客户可能有许多不同的配置或安装了不同版本的软件依赖,而这些问题也会导致应用程序不可用。

容器镜像通过将所有软件捆绑到一个单元中的方式,解决了依赖管理问题。你可以将所有软件库、可执行文件和配置文件一起交付。软件通过容器技术与主机隔离。通常,应用程序需要跟主机交互的唯一部分是主机内核。

开发人员、质量工程师和客户运行完全相同的容器化环境和应用程序,有助于保证运行环境的一致性,并限制了可能由错误配置引起的bug数量。

人们经常将容器与虚拟机进行比较,因为两者都具有在单个节点运行多个被隔离的应用程序的特性。当使用虚拟机时,你需要管理整个虚拟机操作系统和被隔离的应用程序。你需要管理不同内核、init 系统、日志系统、安全更新、备份等的完整生命周期。系统不仅需要处理应用程序的开销,还需要处理整个操作系统的运行开销。在容器世界里,你运行的只有容器化应用程序,不需要进行操作系统管理,也没有其他开销。图1-4展示了3个应用程序在3个不同的虚拟机中运行。

图1-4 在3个虚拟机中运行3个应用程序的物理机

使用虚拟机时,你最终需要管理四个操作系统。而使用容器时,这3个应用程序仅在其所需的用户空间下运行,你只需要管理一个操作系统,如图1-5所示。

图1-5 以容器化方式运行3个应用程序的物理机

1.2.2 容器镜像推动微服务的发展

将应用程序打包在容器镜像中允许在同一个物理机安装多个有冲突要求的应用程序。例如,一个应用程序可能需要的C库版本与另一个应用程序所需的C库版本不同,使得这些应用程序不能同时安装。图 1-6 展示了在不使用容器的情况下运行在操作系统上的传统应用程序。

容器可以在其容器镜像中包含正确的C库,每个镜像都可能包含特定于容器应用程序的不同版本的库。你可以运行来自完全不同版本的应用程序。

如图1-7所示,容器让运行相同应用程序的多个实例变得非常简单。容器镜像鼓励将单个服务或者应用程序打包到单个容器中。通过容器,你可以很方便地通过网络建立多个应用程序之间的连接。

你可以构建3个不同的容器镜像,然后通过将它们连接在一起来构建微服务,而不是设计具有Web前端、负载均衡器和数据库的单体应用程序。微服务使得你和其他用户可以尝试运行多个数据库和Web前端,然后将它们编排在一起。容器化的微服务使软件的共享和复用成为可能。

图1-6 运行在同一个服务器上的传统的LAMP技术栈
(Linux + Apache + MariaDB + PHP/Perl应用程序)

图1-7 LAMP技术栈被打包成单独的微服务容器。由于容器通过网络进行通信,
因此它们可以轻松地移动到其他虚拟机中,使复用变得更加容易

1.2.3 容器镜像格式

一个容器镜像包含3个组件。

一个包含运行应用程序所需的所有软件的目录树。

一个描述rootfs内容的JSON文件。

一个被称为manifest列表的JSON文件,用于将多个镜像连接在一起以支持不同的硬件架构。

目录树被称为rootfs(根文件系统),该组件的布局类似Linux系统的根目录(/)。

第一个JSON文件中定义了在rootfs中运行的可执行文件、工作目录、要使用的环境变量、可执行文件的维护者以及其他有助于识别镜像内容的标签。你可以通过使用podman inspect命令的方式来查看这个JSON文件。

$ podman inspect docker:/ /registry.access.redhat.com/ubi8
{
…
  "created": "2022-01-27T16:00:30.397689Z",  ◁--- 镜像创建的日期
  "architecture": "amd64",  ◁--- 镜像的架构
  "os": "linux",  ◁--- 镜像的操作系统
  "config": {
         "Env": [  ◁--- 镜像开发人员想要在容器中设置的环境变量
 
     "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
            "container=oci"
         ],
         "Cmd": [  ◁--- 在容器启动时要执行的默认命令
                   "/bin/bash"
         ],
         "Labels": {  ◁--- 用于帮助描述镜像内容的标签。这些字段可以是任意形式的,不影响镜像的运行方式,但可用于搜索和描述镜像
                     "architecture": "x86_64",
                     "build-date": "2022-01-27T15:59:52.415605",
       …
}

第二个JSON文件即manifest列表,允许arm64机器上的用户拉取与amd64机器上名称相同的镜像。Podman会根据机器的默认硬件架构使用此manifest列表来拉取对应镜像。Skopeo是一个工具,它使用与Podman相同的底层库,可在github.com/containers/skopeo(参见附录A)上查看其源代码。Skopeo可以提供更低级别的信息输出,以检查容器镜像的结构。在以下示例中,使用skopeo命令和--raw选项来检查registry.access.redhat.com/ubi8镜像的manifest规范。

$ skopeo inspect --raw docker:/ /registry.access.redhat.com/ubi8
{
    "manifests": [
      {
               "digest": "sha256:cbc1e8cea
 8c78cfa1490c4f01b2be59d43ddbb
 ad6987d938def1960f64bcd02c",  ◁--- 当架构和操作系统匹配时,精确拉取的镜像摘要
               "mediaType": "application/vnd.docker.distribution.manifest.v2+json",  ◁--- mediaType描述了镜像的类型,如OCI、Docker等
               "platform": {
               "architecture": "amd64",  ◁--- 镜像的架构摘要:amd64
               "os": "linux"  ◁--- 镜像的操作系统摘要:Linux
               },
               "size": 737
      },
      {
               "digest":  ◁--- 这个段落指向一个不同架构(arm64)的镜像
 "sha256:f52d79a9d0a3c23e6ac4c3c8f2ed8d6337ea47f4e2dfd46201756160ca193308",
               "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
               "platform": {
               "architecture": "arm64",
               "os": "linux"
               },
               "size": 737
      },
…
}

镜像使用Linux tar工具将rootfs和JSON文件打包在一起。然后,这些镜像被存储在称为容器镜像注册服务器(例如docker.io、quay.io和Artifactory)的Web服务器上。Podman等容器引擎可以将这些镜像拷贝到一个物理机上并将它们解压到文件系统中。然后,容器引擎会将镜像的JSON文件、引擎内置的默认值和用户的输入进行合并来创建一个新的容器OCI运行时规范的JSON文件。这个JSON文件是用来描述如何运行该容器化应用程序的。

在最后一步,容器引擎启动一个称为容器运行时(例如runc、crun、Kata或gVisor)的轻量程序。容器运行时会读取容器的JSON文件、内核cgroups、安全约束和命名空间,并最终启动容器的主进程。

1.2.4 容器标准

OCI标准委员会定义了存储和容器镜像的标准格式,以及容器引擎的标准。它创建了OCI镜像格式,该格式标准化了容器镜像和镜像的JSON文件格式。它还创建了OCI运行时规范,该规范标准化了由OCI运行时使用的容器的JSON文件。OCI标准允许其他容器引擎(例如Podman[1])通过遵循这些标准,与存储在容器镜像注册服务器中的所有镜像一起工作,并以与包括Docker在内的所有其他容器引擎完全相同的方式运行它们(请参阅图1-7)。

[1] 其他容器引擎包括Buildah、CRI-O、containerd等。

1.3 有了Docker为什么还要使用Podman

我经常被问到这样一个问题:“既然已经有了Docker,为什么还需要使用Podman呢?”其中一个原因是开源软件的用户可以自由选择。就如操作系统一样,操作系统通常支持各种编辑器、Shell、文件系统和Web浏览器。我相信Podman的设计从根本上是优于Docker的,而且它还提供了多种可提高容器安全性和可用性的功能。

1.3.1 为什么只能用一种方式运行容器

Podman的优势之一在于它是在Docker存在很久之后才推出的。Podman的开发者从完全不同的视角研究了改进Docker的设计方案。因为Docker是开源的,因此Podman使用了Docker的一些代码,同时也符合如开放容器计划(OCI)这样的新标准。Podman和开源社区合作,专注于开发新的功能。

在本节的其余部分,我将介绍改进之处。表1-2描述和比较了Podman和Docker中的一些可用功能。

表1-2 Podman和Docker的功能比较

功能

Podman

Docker

描述

支持所有的OCI和Docker镜像

从容器镜像注册服务器(即quay.io和docker.io)拉取并运行容器镜像。请参阅第2章

启动OCI容器引擎

启动runc、crun、Kata、gVisor和OCI容器引擎。请参阅附录B

简单的命令行界面

Podman和Docker使用相同的命令行。请参阅第2章

与systemd集成

×

Podman支持在容器内部运行systemd和systemd的很多功能。请参阅第7章

fork/exec模型

×

容器是命令的子进程

完全支持用户命名空间

×

只有Podman支持在独立的用户命名空间运行容器。请参阅第6章

客户端-服务器模型

Docker是REST API的守护进程。Podman通过systemd的套接字激活服务来支持REST API。请参阅第9章

支持docker-compose

compose脚本适用于这两种REST API。Podman工作于非特权模式。请参阅第9章

支持docker-py

docker-py Python绑定适用于这两个REST API。Podman在非特权模式下工作。Podman还支持podman-py以运行高级功能。请参阅第9章

无守护进程

×

Podman命令行像传统的命令行工具一样运行,而Docker需要多个以root权限运行的守护进程

支持Kubernetes类pod

×

Podman支持在同一个pod运行多个容器,请参阅第4章

支持Kubernetes YAML

×

Podman可以基于Kubernetes YAML启动容器和pod,同时支持根据运行的容器产生Kubernetes YAML。请参阅第8章

支持Docker Swarm

×

Podman认为多节点容器编排器的未来是Kubernetes,并且不打算支持Swarm

自定义镜像注册服务器

×

Podman支持为短名称扩展配置镜像注册服务器。当你指定短名称时,Docker会硬编码成docker.io。请参阅第5章

自定义缺省值

×

Podman支持完全自定义所有的缺省值,包括安全、命名空间和卷。请参阅第5章

macOS支持

Podman和Docker都支持通过运行Linux虚拟机的方式在macOS上运行容器。请参阅附录E

Windows支持

Podman和Docker都支持在Windows WSL 2或者运行Linux的虚拟机上运行容器。请参阅附录F

Linux支持

所有主流的Linux发行版都支持Podman和Docker。请参阅附录C

软件升级时不停止容器

×

Podman不需要在容器运行时保持运行。由于默认情况下Docker的守护进程在监控容器,因此守护进程停止时所有容器将停止运行

1.3.2 非特权容器

Podman最重要的功能可能是它有能力在非特权(rootless)模式下运行。很多情况下,你不想给用户提供完全的root访问权限,但是用户和开发者仍需要运行容器和构建容器镜像的权限。需要root权限会导致很多对安全敏感的公司无法广泛使用Docker。然而,除了标准登录账户,在Linux中Podman不需要额外的安全功能就可以运行容器。

你可以将Docker客户端以普通用户运行,方法是将用户添加到Docker用户组(/etc/group),但我认为授予此访问权限是在Linux机器上可以做的最危险的事情之一。访问docker.sock允许你通过运行以下命令获得主机的完全root访问权限。在这个命令中,你会将整个主机操作系统根目录挂载到容器的/host目录上。--privileged标志会关闭所有容器安全性。然后你使用chroot命令将当前进程的主目录更改为/host。这意味着在执行chroot命令后,你将进入操作系统的根目录“/”,并具有完全的root特权。

$ docker run -ti --name hacker --privileged -v /:/host ubi8 chroot /host
#

此时,你已经拥有机器的完整root特权,可以“为所欲为”。当你入侵机器后,你可以简单地执行docker rm命令来删除容器和你的所有操作记录。

$ docker rm hacker

当Docker配置为使用默认文件记录日志时,所有启动容器的记录都会被删除。我认为这比在没有root权限的情况下设置sudo更糟糕。因为至少在使用sudo的情况下,你有机会在你的日志文件中看到sudo的执行。

而使用Podman时,运行在系统上的进程始终由用户拥有,并且没有比普通用户更高的能力。即使你跳出容器,进程仍然以你的UID运行,并且系统上的所有操作都记录在审计日志中。Podman的用户不能简单地删除容器并覆盖他们的痕迹。要获取更多信息,请参见第6章。

提示 Docker现在具有类似Podman的非特权运行能力,但几乎没有人以这种方式运行它。只为了启动一个容器而在你的主目录中启动多个服务,这种方式并没有流行起来。

1.3.3 fork/exec模型

Docker是作为REST API服务器构建的。可以说Docker基本上是一个包含多个守护进程的客户端-服务器架构。当用户执行Docker客户端时,会借助一个命令行工具连接到Docker守护进程。然后,Docker守护进程会将镜像拉取到它的存储中,接着连接到containerd守护进程,最后containerd守护进程执行用来创建容器的OCI运行时。Docker守护进程是一个通信平台,负责容器中初始进程(PID1)的stdin、stdout和stderr的读写通信。该守护进程将所有输出信息都发送回Docker客户端。用户会认为容器的进程就像当前会话的子进程一样,但其实在背后存在大量的通信过程。图1-8展示了Docker客户端-服务器架构。

图1-8 Docker的客户端-服务器架构。容器是containerd的直接产物,而不是Docker客户端的。
系统内核感知不到客户端程序和容器之间的关系

总之,Docker客户端与Docker守护进程通信,后者与containerd守护进程通信,containerd守护进程最终启动像runc这样的OCI运行时来真正启动容器的PID1。以这种方式运行容器会使得过程比较复杂。多年来,守护进程中的任何一个故障都会使得所有容器宕机,而且往往难以诊断发生了什么。而Podman的核心工程团队都有着深受UNIX系统哲学影响的操作系统背景。

UNIX和C是按照fork/exec计算模型设计的。基本上,当你运行一个新程序时,像Bash shell这样的父程序会fork(派生)一个新进程,然后将新程序作为旧程序的子程序执行。Podman工程团队认为,通过构建一个工具从容器镜像注册服务器中拉取容器镜像、配置容器存储,然后启动OCI运行时作为容器引擎子进程来启动容器,可以使容器更加简单易用。

在UNIX操作系统中,进程可以通过文件系统和进程间通信(IPC)机制共享内容。操作系统的这些特性使得多个容器引擎可以共享存储,而无须运行守护进程来控制访问和共享内容。除了使用操作系统的文件系统所提供的锁机制,容器引擎之间不需要进行通信。后续章节将探讨这种机制的优缺点。图1-9显示了Podman的架构和通信流程。

图1-9 Podman的fork/exec架构。用户启动Podman来执行OCI运行时,
接着OCI运行时启动容器。容器是Podman的直接产物

1.3.4 Podman是无守护进程的

从根本上来说,Podman是不同于Docker的,因为它是无守护进程的。Podman可以像Docker一样运行所有容器镜像,并使用相同的容器运行时来启动容器。然而,Podman无须多个持续以root权限运行的守护进程就可以实现这些功能。

假设你有一个要在系统启动时运行的Web服务。该Web服务被打包在容器内,因此你需要一个容器引擎。如果使用Docker,你需要将其安装在你的机器上并运行,并且与之相关的每个守护进程都须保持运行状态且接受服务连接。然后,启动Docker客户端以启动Web服务。现在你的容器化应用程序以及所有Docker守护进程都在运行。使用Podman,则仅须使用Podman命令来启动容器,Podman本身并不存在守护进程。Podman创建的容器将持续运行,而且不会产生运行多个守护进程的额外开销。在物联网设备和边缘服务器等低端机器上,更少的开销往往更受欢迎。

1.3.5 用户友好的命令行

Docker的一个非常棒的特性是它具有简单易用的命令行界面。当然,还有其他容器命令行,如RKT、lxc和lxcd,也有自己独立的命令行界面。Podman团队早就意识到,独特的命令行界面并不会有助于Podman获得更多的市场份额。Docker是主导工具,几乎每个想要尝试容器的人都使用Docker命令行界面。此外,如果你在线搜索有关如何使用容器的信息,你几乎肯定会得到Docker命令行的使用示例。所以从一开始,我们就认为Podman必须与Docker命令行相匹配。我们很快就开发了一个命令:alias Docker = Podman。

使用此命令,你可以继续输入Docker命令,但Podman会负责运行你的容器。假如Podman命令行与Docker不同,用户会很容易将其视为Podman的一个bug,并且往往要求Podman做出修改以适应用户的使用习惯。当然,也有一些命令是Podman不支持的,如Docker Swarm。但在大多数情况下,Podman是可以完全替换Docker CLI的。

很多发行版提供了一个名为podman-docker的软件包,该软件包将别名从docker更改为podman并提供手册页的链接。这个别名的修改意味着,当你输入docker ps命令的时候,实际执行的是podman ps命令。如果你运行man docker ps,则会显示podman ps的手册页。图1-10是来自一位Podman用户的推特消息,他将docker命令的别名设置为podman,之后他惊讶地发现他已经使用Podman两个月了,而他一直认为自己使用的是Docker。

早在2018年,Alan Moran就曾发推文说:“我完全忘记了大约两个月前我设置了‘alias docker="podman"’,这真是一场梦。”Joe Thomson回复说:“那是什么提醒了你?”Alan Moran回答:“docker help。”然后Podman help就出现了。

图1-10 关于“alias docker = podman”的推文

1.3.6 支持REST API

Podman可以作为一个由套接字激活的REST API服务来运行,因此允许远程客户端管理和启动Podman容器。Podman支持Docker API以及涉及Podman高级功能的Podman API。通过使用Docker API,Podman支持docker-compose和其他使用docker-py Python绑定的工具。这意味着,即使你的基础设施是使用Docker套接字来启动容器的,你也可以简单地将Docker替换为Podman服务,并继续使用你现有的脚本和工具。第9章会介绍Podman服务。

基于Podman REST API,macOS、Windows和Linux系统上的远程Podman客户端可以与运行在Linux机器上的Podman容器进行交互。附录E和F将介绍如何在macOS和Windows上使用Podman。

1.3.7 与systemd集成

systemd是操作系统上最基础的init系统。Linux系统上的init进程是内核启动时启动的第一个进程。因此,init系统是操作系统上所有进程的“祖先”,可以对所有进程进行监控。Podman想把容器的运行和init系统完全结合起来。用户希望在系统启动时使用systemd启动和停止容器。容器需要支持以下操作。

支持容器内的systemd。

支持套接字激活。

支持通过systemd通知机制来告诉systemd容器化应用程序已完全激活。

允许systemd完全管理容器化应用程序的cgroups和生命周期。

基本上,容器是作为systemd单元文件中的服务来运行的。许多开发人员希望在容器内运行systemd,以便在容器内运行多个系统定义的服务。

然而,Docker社区不同意这一点,并拒绝了所有试图将systemd集成到Docker中的“pull request”。他们认为Docker应该管理容器的生命周期,同时也不想接纳那些想要在容器内运行systemd的用户的想法。

Docker社区认为Docker守护进程应该作为进程的控制器,由Docker守护进程管理容器的生命周期,并在启动时启动和停止容器,而不是systemd。然而,问题在于systemd拥有比Docker更多的功能,包括启动顺序、套接字激活、服务就绪通知等。图 1-11 是第一届 DockerCon 会议上Docker员工的实际工牌,反映了他们对systemd的不认同。

图1-11 DockerCon会议上的
Docker员工工牌

开发人员在设计Podman时就希望确保它与systemd完全集成。当你在容器内运行systemd时,Podman以systemd期望的方式设置容器,并允许它以有限权限作为容器的PID1进程运行。通过systemd单元文件,Podman允许你在容器内运行服务,就像服务在操作系统或者虚拟机中运行一样。Podman支持套接字激活、服务通知和很多其他的systemd单元文件功能。Podman使得生成符合最佳实践的systemd单元文件很简单,以便在systemd服务中运行容器。要获取更多信息,请参阅第7章中关于systemd集成的内容。

Containers项目(https://github.com/containers)是Podman、容器库和其他容器管理工具的所在之处,它希望拥抱操作系统的所有功能并将其完全集成。第 7 章将介绍Podman与systemd的集成。

1.3.8 pod

Podman的优势之一在其名称中就可以看出来。前文就曾提到,Podman实际上是pod manager的缩写。正如Kubernetes官方文档所说,“pod(像海豹群一样,因此有了Podman的Logo,或者说是豌豆荚)是一组(一个或多个)容器;这些容器共享存储、网络资源及有关如何运行这些容器的规范声明”。Podman既可以像Docker一样一次创建一个容器,也可以在一个pod中同时管理多个容器。容器的设计目标之一是将服务拆分到多个独立的容器中,即微服务。然后你可以将这些容器关联起来构建一个更大的服务。pod允许你像管理单个实体一样,将多个服务组合在一起形成一个更大的服务。Podman的目标之一是允许创建并使用pod做一些功能验证。图1-12展示了运行在同一个系统上的两个pod,每个pod包含3个容器。

图1-12 运行在一个主机上的两个pod。每个pod运行两个不同的应用容器和一个infra容器

Podman的podman generate kube命令允许你基于运行的容器和pod生成Kubernetes YAML文件,可以在第7章中看到更多与此相关的介绍。

类似地,Podman的podman play kube命令允许用户执行Kubernetes YAML文件并在你的主机上生成pod和容器。我建议在单个主机上使用Podman运行pod和容器,如果是多台机器则建议使用Kubernetes将用户的pod和容器调度到多台机器上运行并通过用户的基础设施管理。其他项目如kind(https://kind.sigs.k8s.io/docs/user/rootless),正在尝试在Kubernetes的引导下使用Podman来运行pod。

1.3.9 自定义容器镜像注册服务器

Podman等容器引擎支持使用短名称(如ubi8)来拉取镜像,而不需要指定这些镜像所在的注册服务器(registry.access.redhat.com)。完整的镜像名称包含用来拉取镜像的容器镜像注册服务器的名称:registry.access.redhat.com/library/ubi8:latest。表1-3中展示了镜像名称的组成部分。

表1-3 短名称与容器镜像名称映射表

名称

容器镜像注册服务器

镜像仓库

镜像名称

镜像标签

短名称

ubi8

全名称

registry.access.redhat.com

library

ubi8

latest

在使用短名称时,Docker被硬编码为总是从https://docker.io拉取镜像。假如你希望从其他容器镜像注册服务器拉取镜像,则必须指定完整的镜像名称。在下面的示例中,我尝试拉取ubi8/httpd-24镜像,但是失败了,原因是容器镜像在docker.io上并不存在。实际上,该镜像位于registry.access.redhat.com上。

# docker pull ubi8/httpd-24
Using default tag: latest
Error response from daemon: pull access denied for ubi8/httpd-24,
repository does not exist or may require 'docker login': denied: requested
access to the resource is denied

所以,如果我想使用ubi8/httpd-24,我必须输入包括容器镜像注册服务器在内的完整名称。

# docker pull registry.access.redhat.com/ubi8/httpd-24

Docker引擎将docker.io作为首选容器镜像注册服务器,优先级高于其他容器镜像注册服务器。然而Podman在设计之初就允许你指定多个注册服务器,就像你可以使用不同的包管理工具(如dnf、yum和apt)来安装软件包一样。你甚至可以从注册服务器列表中将docker.io选项删除。现在如果你尝试使用Podman拉取ubi8/httpd-24,Podman将会为你提供一个注册服务器列表。

$ podman pull ubi8/httpd-24
? Please select an image:
    registry.fedoraproject.org/ubi8/httpd-24:latest
       ▸ registry.access.redhat.com/ubi8/httpd-24:latest 
    docker.io/ubi8/httpd-24:latest
    quay.io/ubi8/httpd-24:latest

当你做出选择后,Podman会记录短名称别名,不再提示和使用之前选择好的容器镜像注册服务器。Podman还支持很多其他功能,如注册服务器黑名单、只拉取已签名镜像、设置镜像的mirror和指定硬编码的短名称,这样使得特定的短名称直接映射到全名称(请查阅第5章)。

1.3.10 支持多种传输方式

Podman支持多种不同的容器镜像源和目标,这些源和目标被称为传输方式(见表1-4)。Podman可以从容器镜像注册服务器和本地容器存储中拉取镜像,还支持以OCI、OCI TAR、传统的Docker TAR、目录格式存储的镜像,以及直接从Docker守护进程中获取的镜像。Podman命令可以轻松地运行每种格式的镜像。

表1-4 Podman支持的传输方式

传输方式

描述

容器镜像注册服务器(docker)

引用存储在远程容器镜像注册服务器网站上的容器镜像。镜像注册服务器存储和共享容器镜像(例如docker.io和quay.io)

oci

引用符合OCI布局规范的容器镜像。manifest和层TAR包作为单独的文件位于本地目录中

dir

引用符合Docker镜像布局的容器镜像,类似于oci传输方式,但是以旧版的Docker格式存储文件

docker-archive

引用打包到TAR归档文件中的符合Docker镜像布局的容器镜像

oci-archive

引用打包到TAR归档文件中的符合OCI布局规范的容器镜像

docker-daemon

引用存储在Docker守护进程内部存储中的容器镜像

container-storage

引用位于本地存储中的容器镜像。Podman默认使用container-storage来保存本地镜像

1.3.11 完全可定制

容器引擎往往有很多内置常量,比如它们运行时使用的命名空间、SELinux是否启用以及容器运行时运行哪些功能。如果使用Docker,这些常量的值大部分都是硬编码的,并且默认不能被修改。对比来看,Podman则具有完全可定制的配置。

Podman有内置的默认值,但是定义了三处存储其配置文件的位置。

/usr/share/containers/containers.conf:每个发行版可以定义其想要使用的配置。

/etc/containers/containers.conf:可以在这里设置系统级别的参数覆盖。

$HOME/.config/containers/containers.conf:只能在非特权模式下指定。

通过这些配置文件,你可以配置自己想要的Podman默认运行方式。你也可以在默认配置下以更高的安全性来运行Podman。

1.3.12 支持用户命名空间

Podman与用户命名空间完全集成。非特权模式依赖用户命名空间,用户命名空间允许将多个UID分配给一个用户。用户命名空间使得在同一个系统上的不同用户之间保持隔离,因此,你可以让多个非特权用户运行具有多个UID的容器,所有用户之间相互隔离。

用户命名空间可以将容器相互隔离。Podman可轻松启动多个具有唯一用户命名空间的容器,然后内核会基于UID分离,将进程与主机用户隔离并使进程彼此之间也隔离开来。

与此不同,Docker仅支持在单独的用户命名空间运行容器,这意味着所有容器都运行在同一个用户命名空间。一个容器里的root用户与另一个容器里的root用户相同。Docker不支持在不同的用户命名空间运行每个容器,这意味着容器从用户命名空间的角度来看会相互攻击。所以即使Docker支持了这种模式,也几乎没有人使用Docker在独立的用户命名空间运行容器。

1.4 什么时候不使用Podman

与Docker一样,Podman不是容器编排器。Podman是一个以非特权或者特权模式在单个主机上运行容器工作负载的工具。如果你想在多台机器上编排运行容器,则需要更高级别的工具。

我认为现在最好的容器编排工具是Kubernetes。Docker也有一个名为Swarm的编排器,曾经有过一些人气,但现在似乎失宠了。由于Podman团队认为Kubernetes是在多台机器上运行和管理容器的最佳方式,所以Podman并不支持Docker的Swarm功能。目前Podman已被用在不同的编排器中并用于网格/HPC计算,开源开发人员甚至将其添加到Kubernetes前端界面。

1.5 总结

容器技术已经存在多年,但容器镜像和容器镜像注册服务器的引入为开发人员提供了一种更好的软件交付形式。

Podman是一款优秀的容器引擎,适用于几乎所有的单节点容器项目。它对于开发、构建和运行容器化应用程序非常有用。

与Docker一样,Podman易于使用,且具有与Docker完全相同的命令行界面。

Podman支持REST API,它允许远程工具和语言(包括docker-compose)与Podman容器一起工作。

与Docker不同,Podman拥有多项显著的功能,包括支持用户命名空间、多种传输方式、可定制镜像注册服务器、与systemd的高度集成、fork/exec模型以及开箱即用的非特权模式等。

Podman是一种更安全的容器运行方式。

相关图书

相关文章

相关课程