不只有Docker:可选择的容器化工具还有很多……

开源
Docker允许构建、运行、拉取、推送或检查容器镜像,但是对于每个任务来说,其他的可替代工具可能比Docker做得更好。因此,我们必须得探讨一下现状,这也许会让你卸载并完全忘记Docker。

本文转载自公众号“读芯术”(ID:AI_Discovery)。

在过去的容器时代(更确切地说是四年前),Docker是容器角逐赛中的唯一参与者。今非昔比,现在的Docker已经不再是唯一,只是业界全景图中的容器引擎之一。

Docker允许构建、运行、拉取、推送或检查容器镜像,但是对于每个任务来说,其他的可替代工具可能比Docker做得更好。因此,我们必须得探讨一下现状,这也许会让你卸载并完全忘记Docker。

[[352235]]

为什么不使用Docker?

对于已经用了很久docker的人,可能需要花费些功夫去说服自己去考虑转换使用不同的工具。

Docker是一个庞大单一的工具,它尝试做任何事,但通常没有用最好的方法去做。我们最好选择只做一件事,但确实做得很好的专门工具。如果害怕切换不同的工具集,担心不得不学习使用不同的命令行界面(CLI)、不同的API或通常使用不同的概念,那么现在这将不再是问题。

选择本文中显示的任何工具都是完全无缝衔接的,因为它们(包括Docker)都遵循开放容器计划(OCI)下的相同规范。该计划包含有关容器运行时、容器分发和容器镜像的规范,涵盖了使用容器所需的所有功能。借助OCI,你可以选择最符合需求的一组工具,与此同时仍然可以使用与Docker相同的API和CLI命令。

因此,如果你愿意尝试新工具,那么请比较一下Docker及其竞争对手的优势、劣势和功能,看看是否有必要考虑放弃Docker,试试某些新工具。

容器引擎

在将Docker与其他任何工具进行比较时,我们需要按组件对其进行分类,并且首先要谈的是容器引擎。

容器引擎是一种工具,提供了用于处理图像和容器的用户界面,因此不必担心扰乱SECCOMP规则或SELinux策略。它的工作还包括从远程存储库中提取图像并将其扩展到磁盘,似乎也在运行容器,但它实际上的工作是创建带有图像层的容器清单和目录,然后将它们传递到容器运行时,如runc或crun。

目前有许多可用的容器引擎,Docker最主要的竞争对手是Red Hat开发的Podman。与Docker不同,Podman不需要运行守护进程,也不需要root特权,这是Docker长期以来一直关注的问题。

顾名思义,Podman不仅可以运行容器,还可以运行pods。pod是Kubernetes的最小计算单元。它由一个或多个容器组成,执行支持任务。这使Podman用户以后可以更轻松地将其工作负载迁移到Kubernetes。以下是如何在单个pod中运行2个容器的方法:

  1. ~ $ podman podcreate --name mypod 
  2.         ~ $ podman podlist 
  3.              POD ID         NAME   STATUS    CREATED         # OFCONTAINERS   INFRA ID 
  4.         211eaecd307b   mypod  Running   2 minutes ago   1                 a901868616a5 
  5.              ~ $ podman run -d--pod mypod nginx  # Firstcontainer 
  6.         ~ $ podman run -d--pod mypod nginx  # Secondcontainer 
  7.         ~ $ podman ps -a--pod 
  8.              CONTAINERID  IMAGE                           COMMAND               CREATED        STATUS            PORTS  NAMES               POD           POD NAME 
  9.         3b27d9eaa35c  docker.io/library/nginx:latest  nginx -g daemon o...  2 seconds ago Up 1 second ago         brave_ritchie       211eaecd307b  mypod 
  10.         d638ac011412  docker.io/library/nginx:latest  nginx -g daemon o...  5 minutes ago Up 5 minutes ago        cool_albattani     211eaecd307b  mypod 
  11.         a901868616a5  k8s.gcr.io/pause:3.2    

最后,Podman提供了与Docker完全相同的CLI命令,只需执行alias Docker=Podman并假装没有任何更改。

除了Docker和Podman,还有其他的容器引擎,但是笔者认为它们都没有出路,或者都不适合本地开发和使用。具体原因如下:

  • LXD——LXD是用于LXC(Linux容器)的容器管理器(守护进程)。这个工具提供了运行系统容器的能力,这些容器提供了更类似于VMs的容器环境。它位于非常狭窄的空间中,用户不多,所以除非有非常具体的用例,否则最好使用Docker或Podman。
  • CRI-O——当搜索什么是CRI-O时,可能会发现它被描述为容器引擎。不过,它实际上是容器运行时。此外,它也不适合“正常”使用。笔者的意思是,它是专门为Kubernetes运行时(CRI)而构建的,而不是供最终用户使用。
  • rkt——rkt(“火箭”)是CoreOS开发的容器引擎。这里提到这个项目只是为了文章的完整性,因为项目结束了,它的开发也停止了,所以趁早别用它。

构建镜像

容器引擎中,Docker只有一个替换项,但当谈到构建镜像,我们有更多的选择。

首先来介绍Buildah。Buildah是redhat开发的另一个工具,它可以很好地与Podman配合使用。如果已经安装了Podman,可能会注意到Podman build子命令,它实际上只是伪装的Buildah,其二进制文件包含在Podman中。

它的功能遵循与Podman相同的路线,是无守护程序和无根的,并且可以生成OCI兼容的镜像,可以确保你的镜像与Docker构建镜像的运行方式相同。除此之外,Buildah还提供了对图像层的更精细的控制,允许将许多更改提交到单个层中。与Docker相比,Buildah构建的镜像是特定于用户的,因此只能列出自己构建的镜像。

那么,既然Buildah已经包含在podman CLI中,为什么还要使用单独的Buildah CLI?原因在于,buildahcli是podman build中包含的命令的超集,可能不需要接触buildah CLI,但是通过使用它,可能还会发现一些额外有用的特性。

可以看一个小型过程展示:

  1. ~ $ buildah bud-f Dockerfile . 
  2.              ~ $ buildah from alpine:latest  # Create starting container - equivalentto "FROM alpine:latest" 
  3.              Getting image source signatures 
  4.              Copying blobdf20fa9351a1 done  
  5.              Copying configa24bb40132 done  
  6.              Writing manifest toimage destination 
  7.              Storing signatures 
  8.              alpine-working-container  # Name of the temporary container 
  9.              ~ $ buildah runalpine-working-container -- apk add --update --no-cache python3  # equivalent to "RUN apk add--update --no-cache python3" 
  10.              fetchhttp://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz 
  11.              fetchhttp://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz 
  12.              ... 
  13.              ~ $ buildahcommit alpine-working-container my-final-image # Create final image 
  14.              Getting image source signatures 
  15.              Copying blob50644c29ef5a skipped: already exists  
  16.              Copying blob362b9ae56246 done  
  17.              Copying config1ff90ec2e2 done  
  18.              Writing manifest toimage destination 
  19.              Storing signatures 
  20.              1ff90ec2e26e7c0a6b45b2c62901956d0eda138fa6093d8cbb29a88f6b95124c 
  21.              ~# buildah images 
  22.              REPOSITORY               TAG     IMAGE ID      CREATED         SIZE 
  23.              localhost/my-final-imagelatest  1ff90ec2e26e  22 seconds ago  51.4 MB 

从上面的脚本可知,可以仅使用buildah bud来构建镜像,其中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,也可以称为下一代docker build。它是Moby项目的一部分(与Docker一样),可以使用DOCKER_BUILDKIT = 1 dockerbuild作为实验特性启用Docker。

它引入了许多改进和功能,包括并行构建步骤、跳过未使用的阶段、更好的增量构建和无根构建。但另一方面,它仍然需要运行守护程序(buildkitd)。因此,如果不想摆脱Docker,但是想要一些新功能和不错的改进,那么使用buildkit可能是理想选择。

除此之外,还有一些值得一提的内容,但不是笔者的最佳选择:

  • Source-To-Image(S2I)是一个工具包,可直接从源代码构建镜像,而无需Dockerfile。该工具非常适合简单的预期场景和工作流程,但如果不需要太多自定义或项目的布局不理想,那么它很快就会变得笨拙。如果对Docker不太有把握,或者在OpenShift集群上构建镜像,则可以考虑使用S2I,因为使用S2I进行构建是内置功能。
  • Jib是Google的另一种工具,专门用于构建Java镜像。它包括Maven和Gradle插件,可以轻松构建镜像而不会扰乱Dockerfile。
  • 最后是Bazel,它是Google的另一种工具,不仅用于构建容器镜像,而且是一个完整的构建系统。如果只想构建镜像,那么钻研Bazel可能会有些过头,但绝对会是一种不错的学习体验。

 

[[352236]]

 

 

图源:unsplash

 

容器运行时

最后一个难题是容器运行时,它负责运行容器。容器运行时是整个容器生命周期/堆栈的一部分,除非对速度、安全性等有非常特定的要求,否则它不会被轻易扰乱。有以下可选工具:

runc是基于OCI容器运行时规范创建的最受欢迎的容器运行时。Docker(通过容器)、Podman和CRI-O使用了它,所以几乎所有东西都希望使用LXD(它使用LXC)。几乎所有内容都是默认设置,即使你在阅读本文后放弃使用Docker,也很可能仍会使用runc。

还有一种类似runc但令人困惑替代方法,名为crun。这是Red Hat开发的工具,完全用C编写(runc用Go编写)。这使其比runc更快、更高效。它也是OCI兼容的运行时,如果想自己检查一下,可以轻松切换到它。虽然目前不太流行,但它将作为RHEL8.3版本中的替代OCI运行时出现在技术预览中,最终可能会被Podman或CRI-O视为默认的Red Hat产品。

说到CRI-O,之前笔者说过CRI-O并不是容器引擎,而是容器运行时。这是因为CRI-O不包含推送镜像之类的功能,而这正是你所期望的容器引擎的特性。

作为运行时的CRI-O在内部使用runc来运行容器。该运行时不是应该在计算机上尝试使用的运行时,因为它是为在Kubernetes节点上用作运行时而构建的,被描述为“所有Kubernetes所需的运行时,仅此而已”。

因此,除非要设置Kubernetes集群(或OpenShift集群——CRI-O已经是默认值),否则别接触此集群。

最后要讲的是容器化,这是云原生计算基金会(CNCF)即将毕业的项目。这是一个守护程序,可充当各种容器运行时和操作系统的API外观。在后台,它依赖于runc,是Docker引擎的默认运行时。

GoogleKubernetes Engine(GKE)和IBM Kubernetes Service(IKS)也使用它。它是Kubernetes容器运行时界面(与CRI-O相同)的实现,是Kubernetes集群运行时的理想选择。

镜像检查和分发

容器堆栈的最后一部分是镜像检查和分发。这有效地代替了docker inspect,并且(可选地)增加了在远程注册表之间复制/镜像的功能。

唯一可以完成这些任务的工具是Skopeo。它是由Red Hat制造的,并且是Buildah、Podman和CRI-O的随附工具。除了从Docker知道的基本skopeo inspect外,Skopeo还能够使用skopeo copy来复制镜像,这使得可以在远程注册表之间制作镜像,无需先将它们拉到本地注册表。如果使用本地注册表,此功能也可以用作拉取/推送。

另外,笔者还想提到一下Dive,它是一种检查、浏览和分析图像的工具,更加人性化,提供了更具可读性的输出,并且可以更深入地挖掘(或潜水,我想)镜像,并分析和衡量其效率。它也适用于CI管道,可以在其中测量镜像是否“足够有效”。

[[352237]]

图源:unsplash

笔者并非想说服你完全放弃使用Docker,而是希望展示所有工具的全景图以及构建、运行、管理和分发容器及其镜像的所有选项。包括Docker在内的每种工具都有其优缺点,我们必须评估哪种工具最适合工作流程和用例,这一点很重要。

 

责任编辑:赵宁宁 来源: 今日头条
相关推荐

2013-04-19 11:24:19

Ubuntu 13.0GNOME桌面

2009-11-09 17:32:59

Oracle可选择性

2012-11-05 14:38:04

2022-12-09 10:09:24

微软Windows 11

2023-07-31 12:05:38

GIL全局解释器锁

2014-12-17 10:59:28

2012-03-27 14:23:38

Windows 8IE10

2010-03-03 08:57:18

浏览器用户选择

2021-12-03 12:03:21

Windows 11菜单布局应用程序

2021-04-26 16:51:32

开发API网关网络

2021-02-15 18:50:12

谷歌Chrome浏览器

2022-01-12 13:45:09

微软Windows 11Windows

2020-12-07 10:10:06

图形化工具Portai运维

2020-07-29 22:46:59

容器KubernetesPaaS

2020-11-11 14:56:00

Docker容器工具

2010-05-25 16:20:11

VoIP技术服务

2019-04-15 10:30:38

程序员技能开发者

2019-04-22 08:57:46

硅谷996ICU

2023-03-26 19:34:59

Go工具链数据

2018-06-27 17:24:24

华为
点赞
收藏

51CTO技术栈公众号