“Docker死了!”
2020年末,当这个消息传开时,社区陷入了恐慌。
但实际上发生了什么?
>
🎯 本文涵盖内容
- Kubernetes为何排除Docker(真正的原因)
- dockershim是什么,为何成为问题
- containerd、CRI-O等替代运行时是什么
- Docker镜像(docker build)是否仍然可用
- 开发者和运维人员实际需要改变什么
📌 引言 / 背景
2020年12月,Kubernetes官方博客发布了一篇爆炸性的文章。
“Kubernetes is deprecating Docker as a container runtime.”
这一句话点燃了Twitter、Reddit和Slack频道。甚至Kubernetes的联合创始人Joe Beda也在Twitter上写道:
“Fascinating how this docker/docker-shim deprecation has created mass confusion.”
许多人陷入恐慌,问道:“现在不能用Docker了吗?”,“我用docker build创建的镜像是不是都不能用了?”
开门见山地说:无需恐慌。但你需要确切了解发生了什么。
🔍 dockershim是什么?
Kubernetes早期:只有Docker
当Kubernetes首次出现时(大约2014年),Docker Engine是唯一的容器运行时。因此,Kubernetes将Docker支持硬编码到其代码中,这个组件被称为dockershim。
shim最初是指机械组装时用于填充两个部件之间间隙的薄楔子。在软件中,它同样充当连接不同API的适配器。
CRI的出现:标准化的开始
随着时间的推移,rkt、CRI-O、containerd等各种容器运行时相继出现。为了支持所有这些运行时,Kubernetes创建了一个名为CRI(Container Runtime Interface)的标准API。
问题是Docker不支持CRI。考虑到Docker早于CRI出现,这也是理所当然的。
因此,调用路径变成了这样:
kubelet → dockershim → Docker Daemon → containerd → runc → 컨테이너
实际上,Docker并不直接下载镜像或启动容器。其内部的containerd完成了这项工作。这意味着Kubernetes为了运行一个容器,必须经过kubelet → dockershim → Docker → containerd这一漫长的中间过程。

🔍 为何移除Docker?3个真正的原因
1️⃣ 维护负担过重
dockershim从一开始就是临时解决方案(故名:shim)。随着维护负担的增加,Kubernetes维护者开始质疑:“仅仅因为Docker不实现CRI标准,我们是否必须继续承担这个负担?”
2️⃣ 不必要的中间步骤
Kubernetes开发者希望移除Docker的一个重要原因就是中间步骤过多。仅仅启动一个容器,就有太多的消息在应用程序之间传递。
直接连接containerd可以简化路径,如下所示:
kubelet → containerd (CRI plugin 내장) → runc → 컨테이너
即使每个容器只节省0.1秒,在处理数百个容器的环境中,也能感受到明显的性能差异。
3️⃣ 与新技术的兼容性问题
cgroups v2、用户命名空间(user namespaces)等新功能与dockershim大多不兼容。移除dockershim支持将有助于在这些领域进行进一步开发。
🗓️ 时间线:这一切何时发生?
| 时间 | 事件 |
| 2016年 | Kubernetes CRI 规范发布 |
| 2020年12月 | Kubernetes v1.20: dockershim 正式宣布弃用 |
| 2021年 | 因社区反对,移除计划推迟一次 |
| 2022年4月 | Kubernetes v1.24: dockershim 完全移除 |
v1.20中正式弃用,但由于通知不充分,社区发生了恐慌。大部分混乱源于误解,例如“Docker这家公司要消失了吗?”或“用Docker构建的镜像将无法运行了吗?”
🔍 那么现在用什么?
containerd — 事实上的标准
containerd最初由Docker开发,后捐赠给CNCF(Cloud Native Computing Foundation),是一个通用的容器运行时。它管理容器的生命周期,可在Kubernetes内部和外部使用。
AWS EKS、Azure AKS、Google GKE等主要的托管Kubernetes服务已经将containerd作为默认运行时。如果您使用Azure,您的AKS节点已经运行着containerd。
CRI-O — 专为Kubernetes设计的轻量级运行时
CRI-O是Red Hat主导的一个项目,是一个专为Kubernetes设计的轻量级运行时。主要在OpenShift环境中可见。
cri-dockerd — 如果您想继续使用Docker
Mirantis和Docker决定在dockershim从Kubernetes中移除后,将其作为一个独立的开源CRI接口进行维护。安装cri-dockerd仍然允许您使用Docker作为运行时,但这会增加额外的安装负担。
💻 实际发生了什么变化?(运维人员视角)
容器检查命令的变化
# ❌ 现在在节点上运行这个将不会显示任何内容
docker ps
# ✅ 在containerd环境下,应该使用这个
crictl ps
# ✅ 或者通过指定命名空间
ctr -n k8s.io containers list
运行时检查方法
# 检查节点上正在使用的运行时
kubectl get node -o wide
# 可以在 CONTAINER-RUNTIME 列中查看
# 例如: containerd://1.7.x
containerd 安装和基本配置 (基于 Ubuntu)
# 安装 containerd
sudo apt-get update
sudo apt-get install -y containerd
# 生成默认配置文件
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# 启用 systemd cgroup 驱动 (Kubernetes 推荐)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/'
/etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
镜像构建仍然可以使用 Docker ✅
# 这仍然完全有效
docker build -t myapp:v1.0 .
docker push myregistry.io/myapp:v1.0
# 部署到 Kubernetes 时镜像格式相同
kubectl apply -f deployment.yaml
⚠️ 注意事项 / 常见错误
1. 不要尝试用 docker ps 调试 Pod
在使用containerd的节点上,运行docker ps将不会显示Pod容器。当使用containerd等其他运行时时,您无法通过docker ps或docker inspect命令获取容器信息。请使用kubectl exec、kubectl logs或crictl ps。
2. 依赖 Docker daemon 的工具需要检查
如果Kubernetes基础设施外部安装了依赖Docker命令的脚本或守护进程,例如监控代理或安全代理,则需要进行检查。
3. 私有仓库配置位置不同
Docker中通过daemon.json管理的私有仓库镜像设置,在containerd中需要在/etc/containerd/config.toml中进行配置。
# /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."myregistry.io"]
endpoint = ["https://myregistry.io"]
✅ 总结 / 结束语
Docker并没有死。它的角色只是被分离了。
| 角色 | 工具 | 状态 |
| 镜像构建 | docker build | ✅ 仍然有效 |
| 镜像推送 | docker push | ✅ 仍然有效 |
| 本地开发 | Docker Desktop | ✅ 仍然有效 |
| K8s 容器运行时 | containerd / CRI-O | ✅ 当前标准 |
| dockershim | 已移除 | ❌ v1.24起不再有 |
Docker提供了许多UX改进功能,使得人类在开发工作中可以非常容易地进行交互。然而,Kubernetes不是人类,因此它不需要这些UX改进功能。这就是Kubernetes选择直接与Docker的核心引擎containerd对话的原因。
推荐的下一步:
- 检查当前运行的Kubernetes集群的运行时:kubectl get node -o wide
- 熟悉crictl命令(containerd环境调试必备)
- 使用AKS/EKS/GKE时,查看运行时默认值文档

发表回复