不只有docker:可选择的容器化工具还有很多……
全文共6246字 , 预计学习时长16分钟
文章图片
图源:unsplash
在过去的容器时代(更确切地说是四年前) , Docker是容器角逐赛中的唯一参与者 。 今非昔比 , 现在的Docker已经不再是唯一 , 只是业界全景图中的容器引擎之一 。
Docker允许构建、运行、拉取、推送或检查容器镜像 , 但是对于每个任务来说 , 其他的可替代工具可能比Docker做得更好 。 因此 , 我们必须得探讨一下现状 , 这也许会让你卸载并完全忘记Docker 。
为什么不使用Docker?
对于已经用了很久docker的人 , 可能需要花费些功夫去说服自己去考虑转换使用不同的工具 。
Docker是一个庞大单一的工具 , 它尝试做任何事 , 但通常没有用最好的方法去做 。 我们最好选择只做一件事 , 但确实做得很好的专门工具 。 如果害怕切换不同的工具集 , 担心不得不学习使用不同的命令行界面(CLI)、不同的API或通常使用不同的概念 , 那么现在这将不再是问题 。
选择本文中显示的任何工具都是完全无缝衔接的 , 因为它们(包括Docker)都遵循开放容器计划(OCI)下的相同规范 。 该计划包含有关容器运行时、容器分发和容器镜像的规范 , 涵盖了使用容器所需的所有功能 。 借助OCI , 你可以选择最符合需求的一组工具 , 与此同时仍然可以使用与Docker相同的API和CLI命令 。
因此 , 如果你愿意尝试新工具 , 那么请比较一下Docker及其竞争对手的优势、劣势和功能 , 看看是否有必要考虑放弃Docker , 试试某些新工具 。
容器引擎
在将Docker与其他任何工具进行比较时 , 我们需要按组件对其进行分类 , 并且首先要谈的是容器引擎 。
容器引擎是一种工具 , 提供了用于处理图像和容器的用户界面 , 因此不必担心扰乱SECCOMP规则或SELinux策略 。 它的工作还包括从远程存储库中提取图像并将其扩展到磁盘 , 似乎也在运行容器 , 但它实际上的工作是创建带有图像层的容器清单和目录 , 然后将它们传递到容器运行时 , 如runc或crun 。
目前有许多可用的容器引擎 , Docker最主要的竞争对手是RedHat开发的Podman 。 与Docker不同 , Podman不需要运行守护进程 , 也不需要root特权 , 这是Docker长期以来一直关注的问题 。
顾名思义 , Podman不仅可以运行容器 , 还可以运行pods 。 pod是Kubernetes的最小计算单元 。 它由一个或多个容器组成 , 执行支持任务 。 这使Podman用户以后可以更轻松地将其工作负载迁移到Kubernetes 。 以下是如何在单个pod中运行2个容器的方法:
~$podmanpodcreate--namemypod~$podmanpodlistPODIDNAMESTATUSCREATED#OFCONTAINERSINFRAID211eaecd307bmypodRunning2minutesago1a901868616a5~$podmanrun-d--podmypodnginx#Firstcontainer~$podmanrun-d--podmypodnginx#Secondcontainer~$podmanps-a--podCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMESPODPODNAME3b27d9eaa35cdocker.io/library/nginx:latestnginx-gdaemono...2secondsagoUp1secondagobrave_ritchie211eaecd307bmypodd638ac011412docker.io/library/nginx:latestnginx-gdaemono...5minutesagoUp5minutesagocool_albattani211eaecd307bmypoda901868616a5k8s.gcr.io/pause:3.2最后 , Podman提供了与Docker完全相同的CLI命令 , 只需执行aliasDocker=Podman并假装没有任何更改 。
【不只有docker:可选择的容器化工具还有很多……】除了Docker和Podman , 还有其他的容器引擎 , 但是笔者认为它们都没有出路 , 或者都不适合本地开发和使用 。 具体原因如下:
·LXD——LXD是用于LXC(Linux容器)的容器管理器(守护进程) 。 这个工具提供了运行系统容器的能力 , 这些容器提供了更类似于VMs的容器环境 。 它位于非常狭窄的空间中 , 用户不多 , 所以除非有非常具体的用例 , 否则最好使用Docker或Podman 。
·CRI-O——当搜索什么是CRI-O时 , 可能会发现它被描述为容器引擎 。 不过 , 它实际上是容器运行时 。 此外 , 它也不适合“正常”使用 。 笔者的意思是 , 它是专门为Kubernetes运行时(CRI)而构建的 , 而不是供最终用户使用 。
·rkt——rkt(“火箭”)是CoreOS开发的容器引擎 。 这里提到这个项目只是为了文章的完整性 , 因为项目结束了 , 它的开发也停止了 , 所以趁早别用它 。
构建镜像
容器引擎中 , Docker只有一个替换项,但当谈到构建镜像 , 我们有更多的选择 。
首先来介绍Buildah 。 Buildah是redhat开发的另一个工具 , 它可以很好地与Podman配合使用 。 如果已经安装了Podman , 可能会注意到Podmanbuild子命令 , 它实际上只是伪装的Buildah , 其二进制文件包含在Podman中 。
它的功能遵循与Podman相同的路线 , 是无守护程序和无根的 , 并且可以生成OCI兼容的镜像 , 可以确保你的镜像与Docker构建镜像的运行方式相同 。 除此之外 , Buildah还提供了对图像层的更精细的控制 , 允许将许多更改提交到单个层中 。 与Docker相比 , Buildah构建的镜像是特定于用户的 , 因此只能列出自己构建的镜像 。
那么 , 既然Buildah已经包含在podmanCLI中 , 为什么还要使用单独的BuildahCLI?原因在于 , buildahcli是podmanbuild中包含的命令的超集 , 可能不需要接触buildahCLI , 但是通过使用它 , 可能还会发现一些额外有用的特性 。
可以看一个小型过程展示:
~$buildahbud-fDockerfile.~$buildahfromalpine:latest#Createstartingcontainer-equivalentto''FROMalpine:latest''GettingimagesourcesignaturesCopyingblobdf20fa9351a1doneCopyingconfiga24bb40132doneWritingmanifesttoimagedestinationStoringsignaturesalpine-working-container#Nameofthetemporarycontainer~$buildahrunalpine-working-container--apkadd--update--no-cachepython3#equivalentto''RUNapkadd--update--no-cachepython3''fetchhttp://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gzfetchhttp://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz...~$buildahcommitalpine-working-containermy-final-image#CreatefinalimageGettingimagesourcesignaturesCopyingblob50644c29ef5askipped:alreadyexistsCopyingblob362b9ae56246doneCopyingconfig1ff90ec2e2doneWritingmanifesttoimagedestinationStoringsignatures1ff90ec2e26e7c0a6b45b2c62901956d0eda138fa6093d8cbb29a88f6b95124c~#buildahimagesREPOSITORYTAGIMAGEIDCREATEDSIZElocalhost/my-final-imagelatest1ff90ec2e26e22secondsago51.4MB从上面的脚本可知 , 可以仅使用buildahbud来构建镜像 , 其中bud代表使用Dockerfile进行构建 , 但是还可以使用更多的脚本化方法 , 通过Buildahs的from、run和copy , 这与Dockerfile中的命令等效 。
接下来是Google的Kaniko 。 Kanik也与Dockerfile构建容器镜像 , 类似于Buildah , 它也不需要守护进程 。 其与Buildah的主要区别在于 , Kaniko更专注于在Kubernetes中构建镜像 。
Kanik使用gcr.io/kaniko-project/executor作为镜像运行 , 这对于Kubernetes有意义 , 但对于本地构建而言并不方便 , 且无法达到目的 , 因为需要使用Docker运行Kaniko镜像来构建新镜像 。
话虽如此 , 如果正在寻找用于在Kubernetes集群中构建镜像的工具(例如在CI/CD管道中) , 无守护进程并且(也许)更安全 , Kaniko可能是一个不错的选择 。
不过 , 根据笔者的个人经验 , 同时使用Kaniko和Buildah在Kubernetes/OpenShift集群中构建镜像 , 笔者认为两者都可以很好地完成工作 , 但是使用Kaniko时 , 笔者看到了一些随机的构建崩溃 , 并且在将镜像推送到注册表时失败了 。
Docker的第三个竞争者是buildkit , 也可以称为下一代dockerbuild 。 它是Moby项目的一部分(与Docker一样) , 可以使用DOCKER_BUILDKIT=1dockerbuild作为实验特性启用Docker 。
它引入了许多改进和功能 , 包括并行构建步骤、跳过未使用的阶段、更好的增量构建和无根构建 。 但另一方面 , 它仍然需要运行守护程序(buildkitd) 。 因此 , 如果不想摆脱Docker , 但是想要一些新功能和不错的改进 , 那么使用buildkit可能是理想选择 。
除此之外 , 还有一些值得一提的内容 , 但不是笔者的最佳选择:
·Source-To-Image(S2I)是一个工具包 , 可直接从源代码构建镜像 , 而无需Dockerfile 。 该工具非常适合简单的预期场景和工作流程 , 但如果不需要太多自定义或项目的布局不理想 , 那么它很快就会变得笨拙 。 如果对Docker不太有把握 , 或者在OpenShift集群上构建镜像 , 则可以考虑使用S2I , 因为使用S2I进行构建是内置功能 。
·Jib是Google的另一种工具 , 专门用于构建Java镜像 。 它包括Maven和Gradle插件 , 可以轻松构建镜像而不会扰乱Dockerfile 。
·最后是Bazel , 它是Google的另一种工具 , 不仅用于构建容器镜像 , 而且是一个完整的构建系统 。 如果只想构建镜像 , 那么钻研Bazel可能会有些过头 , 但绝对会是一种不错的学习体验 ,
文章图片
图源:unsplash
容器运行时
最后一个难题是容器运行时 , 它负责运行容器 。 容器运行时是整个容器生命周期/堆栈的一部分 , 除非对速度、安全性等有非常特定的要求 , 否则它不会被轻易扰乱 。 有以下可选工具:
runc是基于OCI容器运行时规范创建的最受欢迎的容器运行时 。 Docker(通过容器)、Podman和CRI-O使用了它 , 所以几乎所有东西都希望使用LXD(它使用LXC) 。 几乎所有内容都是默认设置 , 即使你在阅读本文后放弃使用Docker , 也很可能仍会使用runc 。
还有一种类似runc但令人困惑替代方法 , 名为crun 。 这是RedHat开发的工具 , 完全用C编写(runc用Go编写) 。 这使其比runc更快、更高效 。 它也是OCI兼容的运行时 , 如果想自己检查一下 , 可以轻松切换到它 。 虽然目前不太流行 , 但它将作为RHEL8.3版本中的替代OCI运行时出现在技术预览中 , 最终可能会被Podman或CRI-O视为默认的RedHat产品 。
说到CRI-O , 之前笔者说过CRI-O并不是容器引擎 , 而是容器运行时 。 这是因为CRI-O不包含推送镜像之类的功能 , 而这正是你所期望的容器引擎的特性 。
作为运行时的CRI-O在内部使用runc来运行容器 。 该运行时不是应该在计算机上尝试使用的运行时 , 因为它是为在Kubernetes节点上用作运行时而构建的 , 被描述为“所有Kubernetes所需的运行时 , 仅此而已” 。
因此 , 除非要设置Kubernetes集群(或OpenShift集群——CRI-O已经是默认值) , 否则别接触此集群 。
最后要讲的是容器化 , 这是云原生计算基金会(CNCF)即将毕业的项目 。 这是一个守护程序 , 可充当各种容器运行时和操作系统的API外观 。 在后台 , 它依赖于runc , 是Docker引擎的默认运行时 。
GoogleKubernetesEngine(GKE)和IBMKubernetesService(IKS)也使用它 。 它是Kubernetes容器运行时界面(与CRI-O相同)的实现 , 是Kubernetes集群运行时的理想选择 。
镜像检查和分发
容器堆栈的最后一部分是镜像检查和分发 。 这有效地代替了dockerinspect , 并且(可选地)增加了在远程注册表之间复制/镜像的功能 。
唯一可以完成这些任务的工具是Skopeo 。 它是由RedHat制造的 , 并且是Buildah、Podman和CRI-O的随附工具 。 除了从Docker知道的基本skopeoinspect外 , Skopeo还能够使用skopeocopy来复制镜像 , 这使得可以在远程注册表之间制作镜像 , 无需先将它们拉到本地注册表 。 如果使用本地注册表 , 此功能也可以用作拉取/推送 。
另外 , 笔者还想提到一下Dive , 它是一种检查、浏览和分析图像的工具 , 更加人性化 , 提供了更具可读性的输出 , 并且可以更深入地挖掘(或潜水 , 我想)镜像 , 并分析和衡量其效率 。 它也适用于CI管道 , 可以在其中测量镜像是否“足够有效” 。
文章图片
图源:unsplash
笔者并非想说服你完全放弃使用Docker , 而是希望展示所有工具的全景图以及构建、运行、管理和分发容器及其镜像的所有选项 。 包括Docker在内的每种工具都有其优缺点 , 我们必须评估哪种工具最适合工作流程和用例 , 这一点很重要 。
文章图片
留言点赞关注
我们一起分享AI学习与发展的干货
如转载 , 请后台留言 , 遵守转载规范
推荐阅读
- 量化|量化大师麦教授:美好的不确定性
- 结核|再见吧,“结核君”
- 减肥也能吃的小零食,营养美味,低脂低热量,多吃也不怕!
- 这款抹茶麻薯软欧,简单好做,满满坚果馅,好吃还不腻
- 1碗面粉,不加水,锅里蒸一蒸,做香甜可口的发糕,比蛋糕还香
- 扇贝最好吃的做法,适合冬日里吃,做法简单好吃不腻,家人超爱吃
- 从小就馋此口,比肉香多了,几块钱做一大盘,咋吃都不腻
- 盐酥烧饼这做法,皮酥里软吃着香,不醒面照样层层酥脆,省时间
- 番茄炒鸡蛋先炒番茄还是先炒鸡蛋?其实都不对,正确方法送给你
- 一碗糯米,半个南瓜,香甜软糯,好吃不上火,比南瓜饼香,太好吃