当前位置: 首页 > 科技观察

Docker不再是唯一的选择

时间:2023-03-15 23:57:34 科技观察

Docker不是唯一的容器化工具,可能还有更好的选择......在容器的早期(实际上更像是4年前),Docker是唯一的工具容器游戏玩家。但现在情况不同了,Docker不再是唯一的,而只是容器引擎中的一种。Docker允许我们构建、运行、拉取、推送或检查容器映像,但是对于每项任务,还有其他替代工具甚至可能比Docker做得更好。所以,让我们探索一下,然后卸载(也许),然后完全忘记Docker……那么,为什么不再使用Docker?如果您长期使用Docker,它可能真的会说服您考虑其他工具,必须先提供一些证据。首先,Docker是一个单一的工具。它试图涵盖所有功能,这通常不是最佳做法。大多数时候,我们只是选择一个专门的工具来做一件事,而且做得非常好,非常精细。如果害怕切换到不同的工具集是因为您必须学习使用不同的CLI、API或不同的概念,那么这就不是问题。本文中介绍的任何工具都可以完全无缝,因为它们(包括Docker)遵循OCI(开放容器计划)下的相同规范。它们包含容器运行时、容器分发和容器镜像的规范,涵盖了使用容器所需的所有功能。使用OCI,您可以选择一组最适合您需求的工具,同时仍然享受与Docker相同的API和CLI命令。所以,如果您愿意尝试新工具,让我们比较Docker及其竞争对手的优缺点和特性,看看是否值得考虑放弃Docker并使用一些新的闪亮工具。ContainerEngines将Docker与其他工具进行比较时,我们需要将其分解为组件,首先我们来说说容器引擎。ContainerEngine是一种工具,它提供了一个用于处理图像和容器的用户界面,这样您就不必处理诸如SECCOMP规则或SELinux策略之类的事情。它的工作还包括从远程存储库中提取图像并将它们扩展到磁盘。它似乎也运行容器,但实际上它的工作是创建容器清单和带有图像层的目录。然后它将它们传递给容器运行时,如runC或Crun(稍后我们将讨论)。已经有很多容器引擎,但Docker最突出的竞争对手是由RedHat开发的Podman。与Docker不同,Podman不需要守护进程运行,也不需要root权限,这是Docker长期以来关注的问题。顾名思义,Podman不仅可以运行容器,还可以运行Pod。如果你不熟悉pod的概念,其实简单概括就是Pod是Kubernetes的最小计算单元。它由一个或多个容器(主容器和执行支持任务的sidecar)组成,这使得Podman用户以后可以更轻松地将他们的工作负载迁移到Kubernetes。因此,作为一个简单的演示,这里是如何在一个Pod中运行两个容器:podCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMESPODPODNAME3b27d9eaa35cdocker.io/library/nginx:latestnginx-gdaemono...2secondsagoUp1secondagobrave_ritchie211eaecd307bmypodd638ac011412docker.io/library/nginx:latestnginx-gdaemono...5minutesagoUp5minutesagocool_albattani211eaecd307bmypoda901868616a5k8s.gcr.io/pause:3.26minutesagoUp5最后,Podman提供DockerhastheexactsameCLIcommands,所以只需执行aliasdocker=podman并假装什么都没有改变。除了Docker和Podman,还有其他的容器引擎,但我个人认为都是没有前途的技术,或者不适合本地开发使用。但是,要了解全貌,至少要看看里面有什么:LXD-LXC(Linux容器)是一个容器管理器(守护进程)。该工具提供了运行系统容器的能力,这些容器提供了更像VM的容器环境。它在一个非常狭窄的空间内,用户很少,所以除非你有一个非常具体的实例,否则你最好使用Docker或Podman。CRI-O-当你谷歌什么是CRI-O时,你可能会发现它被描述为容器引擎。然而,它实际上只是一个容器运行时。它实际上不是引擎,也不适合“正常”使用。我的意思是,它是专门为Kubernetes运行时(CRI)而构建的,而不是为最终用户消费而构建的。Rkt-rkt(“rocket”)是由CoreOS开发的容器引擎。这里提到这个项目只是为了完整性,因为项目已经结束并且开发已经停止-所以没有必要再使用它了。对于构建镜像的容器引擎,Docker一般是唯一的选择。但是,在构建图像时,有很多选择。首先介绍一下Buildah。Buildah是RedHat开发的另一个工具,与Podman配合得很好。如果您安装了Podman,您可能已经注意到podmanbuild子命令,它实际上只是变相的Buildah,因为它的二进制文件已经包含在Podman中。至于它的特点,它沿袭了Podman的相同路线——daemonless和rootless,并且遵循OCI的镜像标准,所以它保证构建的镜像与Docker构建的镜像是一样的。它还能够从Dockerfile或更恰当地命名为Containerfile构建图像,Dockerfile和Containerfile是相同的,只是命名不同。此外,Buildah还提供了对镜像层更细粒度的控制,允许在单个层中提交更多更改。唯一的例外和(在我看来)与Docker的不同之处在于,Buildah构建的镜像是基于用户的,因此用户只能列出自己构建的镜像。然后,考虑到Buildah已经包含在PodmanCLI中,您可能会问,为什么要使用单独的BuildahCLI?BuildahCLI是podmanbuild中包含的命令的超集,因此基本上不需要单独接触BuildahCLI,但是通过使用它,您可能还会发现一些额外的有用的功能(有关podmanbuild和podmanbuild之间差异的详细信息,请参阅此帖子和构建)。现在,我们来看看一个演示:~$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命令(FROMimage,RUN...,COPY...)接下来是Google的Kaniko。Kaniko还从Dockerfile构建容器镜像,类似于Buildah,并且不需要守护进程。与Buildah的主要区别在于Kaniko更专注于在Kubernetes中构建镜像。Kaniko使用gcr.io/kaniko-project/executor作为镜像运行。这适用于Kubernetes,但对于本地构建来说不是很方便,并且有些违背了它的目的,因为我们必须先使用Docker运行Kaniko镜像,然后再构建镜像。也就是说,如果您选择在Kubernetes集群中(例如在CI/CD管道中)构建映像的工具,那么Kaniko可能是一个不错的选择,因为它是无守护程序且(可能)更安全。根据我的个人经验——我在Kubernetes/OpenShift集群中使用Kaniko和Buildah来构建镜像,我认为两者都很好地完成了工作,但是当使用Kaniko时,我看到一些将镜像导入When存储库时,会有随机构建崩溃和失败。第三个竞争者是Buildkit,也可以称为下一代Docker构建。它是Moby项目的一部分。在Docker中,它可以作为一项实验性功能启用,使用DOCKER_BUILDKIT=1Docker构建...那么,它的核心价值到底是什么?它引入了许多改进和很酷的功能,包括并行构建、跳过未使用的阶段、更好的增量构建和无根构建。然而,另一方面,它仍然需要一个正在运行的守护进程(buildkitd)才能运行。所以,如果你不想摆脱Docker,而是想要一些新的特性和更好的改进,那么使用Buildkit可能是最好的选择。和以前一样,这里我们也有一些“光鲜亮丽的产品”,它们也有非常具体的场景,虽然不是我们的首选:Source-To-Image(S2I)是一个不需要直接从源代码中获取Dockerfile的工具一个工具包用于构建图像。该工具适用于简单的、预期的场景和工作流,但如果自定义过多,或者项目没有预期的布局,您很快就会发现该工具既烦人又笨拙。如果您对Docker不是很有信心,或者如果您正在OpenShift集群上构建镜像,那么您可能会尝试考虑使用S2I,因为使用S2I构建是一项内置功能。Jib是Google的另一个专门用于构建Java图像的工具。它包括Maven和Gradle插件,可以在不干扰Dockerfile的情况下轻松构建图像。最后但同样重要的是Bazel,谷歌的另一个工具。它不仅仅是用于构建容器镜像,而是一个完整的构建系统。如果您只是想构建一个图像,那么深入研究Bazel可能有点矫枉过正,但这绝对是一种很好的学习体验,所以如果您想尝试一下,rules_docker绝对是一个不错的起点。容器运行时的最后一大块是容器运行时,它负责运行容器。容器运行时是整个容器生命周期/堆栈的一部分,除非您对速度、安全性等有一些非常具体的要求,否则您通常不需要干涉它。所以,如果读者看腻了,可以跳过这部分。如果不是,那么容器运行时的选择如下:runC是基于OCI容器运行时规范创建的,是最流行的容器运行时。Docker(通过containerd)、Podman和crio使用它,所以几乎一切都依赖于LXD。它是几乎所有产品/工具的默认偏好,所以即使你在阅读本文后放弃Docker,你仍然会使用runC。runC的另一个替代产品是Crun,它具有相似的名称(容易混淆)。这是RedHat开发的一个工具,完全用C写的(runC是用Go写的)。这使得它比runC更快,内存效率更高。考虑到它也是一个OCI兼容的运行时。所以如果你想做一个测试,很容易切换。尽管它现在不是很流行,但在RHEL8.3技术预览中,它作为替代OCI运行时出现,并且考虑到它是RedHat产品,我们最终可能会将其视为Podman或CRI-O的默认偏好。说到CRI-O。前面说了,CRI-O其实不是容器引擎,而是容器运行时。这是因为CRI-O不包含推送图像等特性,这是容器引擎的特性。CRI-O作为运行时在内部使用runC来运行容器。通常不需要在一台机器上尝试这个工具,因为它被构建为用作Kubernetes节点上的运行时,正如你所看到的那样,它被描述为“Kubernetes需要的所有运行时,仅此而已”。因此,除非您正在设置Kubernetes集群(或OpenShift集群-CRI-O已经是默认首选项),否则您不太可能会触及它。本节的最后一个内容是containerd,它是CNCF的一个毕业设计。它是一个守护进程,充当各种容器运行时和操作系统的API。在底层,它依赖于runC,即Docker引擎的默认运行时。GoogleKubernetesEngine(GKE)和IBMKubernetesService(IKS)也在使用中。它是Kubernetes容器运行时接口的部署(与CRI-O相同),因此它是Kubernetes集群运行时的一个很好的候选者。图像检测和分发容器堆栈的最后一部分是图像检测和分发。这有效地取代了dockerinspect并且(可选)增加了在远程注册表之间复制/映射图像的能力。这里要提到的唯一可以完成这些任务的工具是Skopeo。它由RedHat开发,作为Buildah、Podman和CRI-O的配套工具。除了我们都知道的来自Docker的基本skopeoinspect之外,Skopeo还能够使用skopeocopy复制镜像,它允许您在远程镜像registry之间映射镜像,而无需先将它们拉到本地存储库。如果您使用本地存储库,此功能也可以用作拉/推。另外,我想提一下Dive,它是一种用于检查、探测和分析图像的工具。它对用户更友好,提供更易读的输出,允许更深入地探索图像,并分析和测量它们的效率。它也适合在CI管道中使用,它可以衡量你的图像是否“足够高效”,或者换句话说——它是否浪费了太多空间。结论本文的目的不是说服大家完全放弃Docker,而是向您展示整个场景以及构建、运行、管理和分发容器及其镜像的所有选项。每个工具,包括Docker,都有其优点和缺点。评估哪组工具最适合您的工作流程和场景非常重要。我真的希望这篇文章能在这方面对你有所帮助。