Docker 向全面集成 containerd 又迈进一步
Docker 在刚刚发布的 Docker Desktop 4.12.0 中,加入了实验特性:进一步集成 containerd,使用 containerd 来管理和存储镜像。
为什么说是“进一步集成”?这就要翻翻 Docker 和 containerd 的历史了。
containerd 的诞生
containerd 最早出现在 Docker Engine 中,后来为了将 Docker Engine 做得更加轻量、快速和健壮,在 2016 年 Docker 将 containerd 从 daemon(dockerd
) 中独立出来,并完成了与 daemon 的集成。独立出来的 containerd 全面支持 OCI(Open Container Initiative)资源的启动和生命周期的管理,也因此 containerd 可以支持 runc(前身是 Docker 中的 libcontainer,后来捐赠给 LF)以外的其他 OCI 实现。2017 年 Docker 将 containerd 捐献给 CNCF;2019 年 2 月,containerd 毕业。
containerd 独立出来之后,发送到 Docker Engine 的请求:
- Docker daemon 完成镜像管理的操作(拉取、更新镜像)
- daemon 会为创建容器进行准备工作(创建 OCI bundles):镜像的信息和运行时的信息。
- daemon 调用 containerd 的 API。
- 收到请求的 containerd 不会直接去操作容器(不直接作为容器的父进程,防止 containerd 挂掉影响容器),而是先创建一个 container-shim 进程。
- container-shim 调用 runc cli 来运行容器,并启动 Unix domain socket 暴露 API 提供给 containerd进行容器的管理。
随着 containerd 的不断演进,除了容器创建和容器声明周期管理以外,从 1.1 开始 containerd 加入了 CRI(Container Runtime Interface)的支持。
CRI
在《源码解析 kubectl port-forward 工作原理》 中层提到 kubelet 会调用 rumtime service 的 gRPC 接口,除了用于 portforward 流的 stream server以外,其实还有实现 CRI 接口 RuntimeService
和 ImageService
的 RuntimeServiceServer
和 ImageServiceServer
。
RuntimeServiceServer
用于接收并处理容器及其生命周期相关的操作,而 ImageServiceServer
则是用来处理镜像相关的操作。containerd 提供了镜像拉取、删除、检查、存储等功能。
既然 containerd 可以进行镜像的管理,而且 Docker 已经在使用,Docker 也没有必要自己继续维护一套相同的功能。
切换到 containerd 的镜像管理
在 Docker Desktop 的设置中启动 containerd 管理镜像后,运行 docker info
会发现存储的驱动从原来的 overlay2
变成了 containerd 的 stargz
。
切换前:
切换后:
既然使用了 containerd 的 snapshotters 来管理存储(挂在容器的根文件系统),就可以支持多种 snapshotters,比如 stargz 的延迟拉取。
此外,得益于 containerd 原生支持多平台镜像的存储,还是因为 snapshotters 的原因,可以使用 docker 来构建多平台的镜像了。
#切换前
docker buildx build -t demo --no-cache --platform linux/amd64,linux/arm64 .
[+] Building 0.0s (0/0)
error: multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use")
切换后:
图片来自 docker 官方博客
总结
使用 containerd 作为 Docker 的镜像管理目前还处于实验性阶段,必可避免会存在问题,使用时请谨慎对待。
随着 Docker Swarm 在容器编排之战中的落败,Kubernetes 的话语权也越来越强。在 Kubernetes 1.24.0 中移除了 docker shim 代码,看起来更像是 containerd 取代了 Docker 曾经的地位,而 Docker 也越来越名声不显。从趋势来看,Docker 未来将会完全集成 containerd。