社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

除了 Docker,我们还有哪些选择?

马哥Linux运维 • 4 年前 • 404 次点击  

所谓三十年河东,三十年河西,曾经在容器领域叱咤风云的 Docker 如今已风光不再。抛开情怀,我们不得不承认,Docker 已经被后浪拍死在沙滩上了……



大约 4 年前的容器领域,Docker 是唯一的选择。

然而,如今情况已然大不同,Docker 不再是是唯一的选择,它只不过是一个容器引擎而已。我们可以用 Docker 构建、运行、拉取、推送或检查容器镜像,但是这里的每一项任务,都可以用其他工具替代,甚至有些工具比 Docker 还好。

所以,下面就让我们来探索一下这个领域,然后卸载和忘记 Docker 吧。

为什么说不要用 Docker 了?

如果长期以来你一直在使用 Docker,那么说服你考虑其他工具可能需要多费点唇舌。

首先,Docker 是一个整体化的工具,它试图做好所有的事情,但往往只会适得其反。在大多数情况下,我们应该选择专门的工具,它可能只做一件事情,但会做到最好。

可能你因为担心需要学习使用不同的 CLI、不同的 API 或接受不同的概念,所以会害怕使用其他工具。但是,请不用担心。本文介绍的任何工具都可以完美地无缝衔接,因为它们(包括 Docker)都遵循同一个 OCI(OpenContainer Initiative,开放容器计划)规范。OCI 包括容器运行时、容器分发和容器镜像的规范,涵盖了使用容器所需的所有功能。

因为有了 OCI,所以你可以自由选择适合自己的需求的工具,与此同时,你可以继续使用与 Docker 相同的 API 和 CLI 命令。

因此,如果你愿意尝试新工具,那么我们就来比较一下 Docker 与其竞争对手的优缺点和功能,看看是否有必要考虑放弃 Docker,并尝试使用一些新鲜出炉的工具。

容器引擎

在比较 Docker 与其他工具时,我们需要分别讨论它的各个组件,首先要讨论的就是容器引擎。

容器引擎是一种工具,它提供了处理镜像与容器的用户界面,这样你就不需要与 SECCOMP 规则或 SELinux 策略苦苦纠缠了。除此之外,容器引擎还可以从远程仓库提取镜像,并将其解压到本地磁盘上。它似乎也运行容器,但是实际上,它的工作是创建容器清单以及镜像层的目录。接着,它将这些文件传递给 runc 或 crun 等容器运行时。

目前有很多容器引擎可供我们使用,不过 Docker 最主要的竞争对手是红帽开发的 Podman。与 Docker 不同,Podman 不需要运行守护进程,也不需要 root 特权,这些都是 Docker 长期以来一直倍受关注的问题。从名字就可以看出来,Podman 不仅可以运行容器,还可以运行 pod。

如果你不熟悉 pod 的话,我可以简单介绍一下:pod 是 Kubernetes 的最小计算单元,由一个或多个容器 (主容器与负责支持主容器的 sidercar 容器) 组成。因此,Podman 用户以后可以很轻松地将他们的工作负载迁移到 Kubernetes。下面,我们通过一个简单的演示来说明如何在一个 Pod 中运行两个容器:

~ $ podman pod create --name mypod
~ $ podman pod list
POD ID        NAME    STATUS    CREATED         # OF CONTAINERS   INFRA ID
211eaecd307b  mypod   Running   2 minutes ago   1                 a901868616a5
 
~ $ podman run -d --pod mypod nginx  # First container
~ $ podman run -d --pod mypod nginx  # Second container
~ $ podman ps -a --pod
 
CONTAINER ID IMAGE                          COMMAND               CREATED        STATUS            PORTS  NAMES               POD           POD NAME
3b27d9eaa35c  docker.io/library/nginx:latest  nginx -g daemon o...  2 seconds ago Up 1 second ago         brave_ritchie      211eaecd307b  mypod
d638ac011412 docker.io/library/nginx:latest nginx -g daemon o...  5 minutesago  Up 5 minutes ago         cool_albattani      211eaecd307b mypod
a901868616a5 k8s.gcr.io/pause:3.2                                  6 minutesago  Up 5 minutes ago         211eaecd307b-infra  211eaecd307b mypod

最后一点,Podman 提供的 CLI 命令与 Docker 完全相同,因此你只需执行

alias docker=podman

然后就像什么都没有发生过一样。

除了 Docker 和 Podman 之外,还有其他容器引擎,但我并不看好它们的发展,或者不适合用于本地开发。

不过,如果你想对容器引擎有一个较为完整的了解,我也可以介绍一些:

LXD:LXD 是 LXC(Linux 容器)的容器管理器(守护进序)。这个工具提供了运行系统容器的能力,而这些系统容器提供了类似于虚拟机的容器环境。该工具比较小众,没有太多用户,所以除非你有非常特殊的用例,否则最好还是使用 Docker 或 Podman。

CRI-O:如果在网上搜索 cri-o 是什么,你可能会发现它被描述成了一种容器引擎。但实际上,它是一种容器运行时。它既不是容器引擎,也不适合“常规”使用。我的意思是说,它是专门作为 Kubernetes 运行时(CRI)而创建的,并不是给最终用户使用的。

rkt:rkt(读作“rocket”)是 CoreOS 开发的容器引擎。这里提到这个项目只是为了清单的完整性,因为这个项目已经结束了,它的开发也停止了,因此你不应该再使用它。

构建镜像

对于容器引擎,实际上 Docker 的替代品只有一种选择(即 Podman)。但是,在构建镜像方面,我们有很多选择。

首先,我们来看一看 Buildah。这也是一款红帽开发的工具,可以很好地与 Podman 协同工作。如果你已经安装了 Podman,可能会注意到 podman build 子命令,因为它的二进制文件已经包含在 Podman 中了,实际上这个命令只是经过包装的 Buildah。

至于功能,Buildah 沿用了 Podman 的方针:没有守护进程,不需要 root 特权,而且生成的是符合 OCI 的镜像,因此你的镜像的运行方式与使用 Docker 构建的镜像完全相同。它还能使用 Dockerfile 或 Containerfile 构建镜像, Dockerfile 与 Containerfile 实际上是同一个东西,只是叫法不同罢了。除此之外,Buildah 还提供了对镜像层更精细的控制,支持提交大量的变更到单个层。我认为,它与 Docker 之间有一个出乎意料的区别(但这个区别是好事),那就是使用 Buildah 构建的镜像特定于用户,因此你可以只列出自己构建的镜像。

你可能会问,既然 Podman CLI 中已经包含了 Buildah,为什么还要使用单独的 Buildah CLI 呢?其实,Buildah CLI 是 podman build 所包含的命令的超集,因此你可能不需要直接使用 BuildahCLI,但是通过使用它,你可能会发现一些额外的功能。

下面,我们来看一个示例:

~ $ buildah bud -f Dockerfile .
 
~ $ buildah from alpine:latest  # Create starting container - equivalent to"FROM alpine:latest"
Getting image source signatures
Copying blob df20fa9351a1 done
Copying config a24bb40132 done
Writing manifest to image destination
Storing signatures
alpine-working-container # Name of the temporary container
~ $ buildah run alpine-working-container -- apk add--update --no-cache python3  # equivalentto "RUN apk add --update --no-cache python3"
fetchhttp://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetchhttp://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
...
 
~ $ buildah commit alpine-working-containermy-final-image  # Create final image
Getting image source signatures
Copying blob 50644c29ef5a skipped: already exists
Copying blob 362b9ae56246 done
Copying config 1ff90ec2e2 done
Writing manifest to image destination
Storing signatures
1ff90ec2e26e7c0a6b45b2c62901956d0eda138fa6093d8cbb29a88f6b95124c
 
~ # buildah images
REPOSITORY              TAG     IMAGE ID      CREATED         SIZE
localhost/my-final-image latest  1ff90ec2e26e 22 seconds ago  51.4 MB

从上面的脚本可以看出,你可以直接使用 buildah bud 构建镜像,其中 bud 代表使用 Dockerfile 进行构建,你也可以使用其他脚本化的方法,比如使用 Buildahs 的 from、run 和 copy,它们分别对应 Dockerfile 中的 FROM、RUN、COPY 命令。

接下来是 Google 的 Kaniko。Kaniko 也是利用 Dockerfile 构建容器镜像,而且与 Buildah 类似,它也不需要守护进程。但它与 Buildah 的主要区别在于,Kaniko 更加侧重于 Kubernetes 中的镜像构建。

Kaniko 本身也要作为镜像(gcr.io/kaniko-project/executor) 运行,这对于Kubernetes 来说是没有问题的,但对于本地构建来说不是很方便,并且在某种程度上违背了构建镜像的目的,因为你需要使用 Docker 运行 Kaniko 镜像才能构建镜像。话虽如此,如果你正在寻找在 Kubernetes 集群中构建镜像的工具 (例如在 CI/CD 管道中),那么 Kaniko 可能是一个不错的选择,因为它不需要守护进程,而且更安全。

以我个人的经验来看,我认为两者都能很好地完成工作,但是使用 Kaniko 时,我遇到了一些随机的构建故障,而且在将镜像推送到仓库时也出现了失败的情况。

我要介绍的第三个工具是 buildkit,也可以称之为 docker build 二代。它是 Moby 项目的一部分(与 Docker一样),只需设置 DOCKER_BUILDKIT=1 docker build,就可以启动这个工具,并作为 Docker 的一个实验性功能使用。那么,这个工具究竟能给你带来什么?它带来了很多改进和很酷的功能,包括并行构建、跳过未使用的阶段、更好的增量构建以及不需要 root 权限等构建。但是,它仍然需要运行守护进程 (buildkitd)。因此,如果你不想摆脱 Docker,同时又想要一些新的功能和改进,那么可以考虑一下 buildkit。

这里,我也会列出一些其他的工具,它们有各自的特定用途,但不是我的首选:

Source-To-Image(S2I):这是一个不使用 Dockerfile,直接根据源代码构建镜像的工具包。这个工具在简单的预期场景和工作流中表现良好,但如果你需要多一些自定义,如果你的项目的结构不符合预期,那么它就变得非常烦人和笨拙。如果你对 Docker 不太满意,或者你在 OpenShift 集群上构建镜像,则可以考虑使用 S2I,因为使用 S2I 构建镜像是它的一个内置功能。

Jib:这是一款由 Google 开发的工具,专门用于构建 Java 镜像。它提供了 Maven 和 Gradle 插件,可以让你轻松地构建镜像,而无需在意 Dockerfile。

Bazel:这也是一款由 Google 开发的工具。它不仅可用于构建容器镜像,而且是一个完整的构建系统。如果你只是想构建镜像,那么使用 Bazel 可能会有点大材小用,但绝对是一种不错的学习体验,如果你愿意,可以先从 rules_docker 着手。

容器运行时

最后我们来说说负责运行容器的容器运行时。容器运行时是整个容器生命周期的一部分,除非你对速度、安全性等有一些非常特殊的要求,否则请不要乱动它。

看到这里,如果你感到厌倦了,则可以跳过这一部分。但是,如果你想了解一下在容器运行时方面,都有哪些选择,则可以看看下面这些:

runc 是一款流行的容器运行时,且符合 OCI 容器运行时规范。Docker(通过containerd)、Podman 和 CRI-O 都在使用它,因此无需我多言。它几乎是所有容器引擎的默认设置,因此即便你在阅读本文后抛弃了 Docker,很可能仍然会使用 runc。

runc 的另一种替代品是 crun。这是一款由红帽开发的工具,全部用 C 语言编写(runc 是用 Go 编写的),所以它比 runc 更快,内存效率更高。由于它也是兼容 OCI 的运行时,所以如果你想试试看的话,应该能很快上手。虽然它现在还不是很流行,但是它即将作为 RHEL 8.3 版本的备选 OCI 运行时,出现在技术预览中,而且考虑到它是红帽的产品,所以最终很可能会成为 Podman 或 CRI-O 的默认配置。

说到 CRI-O,前面我说过,它并不是容器引擎,而是容器运行时。这是因为 CRI-O 没有推送镜像之类的功能,但这些功能是容器引擎应该具备的。CRI-O 内部使用 runc 来运行容器。你不应该在自己的机器上尝试使用这个运行时,因为它的设计就是 Kubernetes 节点上的运行时,而且它是“Kubernetes 所需的唯一的运行时”。因此,除非你要建立 Kubernetes 集群,否则就不应该考虑 CRI-O。

最后一个是 containerd,它是云原生计算基金会即将推出的一个项目。它是一个守护进程,可作为各种容器运行时和操作系统的 API 接口。它后台依赖于 runc,它是 Docker 引擎的默认运行时。Google Kubernetes Engine(GKE)和 IBM Kubernetes Service(IKS)也在使用它。它是 Kubernetes容器运行时接口的一个实现(与 CRI-O 一样),因此是 Kubernetes 集群运行时的理想选择。

镜像的检查与分发

最后一部分内容是镜像的检查与分发,主要是为了替代 docker inspect,并增加在远程仓库之间复制镜像的能力(可选)。

在这里,我要提到的唯一可以完成这些任务的工具是 Skopeo。它由红帽开发,是 Buildah、Podman 和 CRI-O 的附属工具。除了基本的 skopeo inspect(Docker 有相应的命令),Skopeo 还可以通过 skopeo copy 令来复制镜像,因此你可以直接在远程仓库之间复制镜像,无需将它们拉取到本地。如果你使用本地仓库,那么这个功能也可以作为拉取/推送。

另外,我还想提一下 Dive,这是一款检查、探索和分析镜像的工具。它更加人性化,提供了更加方便阅读的输出,而且还可以更深入地挖掘镜像,并分析和测量镜像的效率。此外,它也很适合在 CI 管道中使用,用于衡量你的镜像是否“足够高效”,或者换句话说,是否浪费了太多空间。

总结

本文的目的并不是要说服你完全抛弃 Docker,而是为了向你展示构建、运行、管理和分发容器及其镜像的整个过程以及所有备选工具。每个工具(包括 Docker)都有其优缺点,因此,评估哪些工具最适合你的工作流程和情况才是最重要的,希望本文能在这方面为你提供一些帮助。

参考链接:https://martinheinz.dev/blog/35
文章转自:CSDN 编译 | 弯月    责编 | 张文


公众号专属福利 1 | 

| 2020全新专题课程限时免费中 | 



公众号专属福利 2 | 
| 长按识别免费领取实战手册 | 
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/106513
 
404 次点击