docker

#containerd vs Docker Engine 的关系

不能完全等价替代,而且 crictldocker 的命令不是一回事,定位完全不同。这里容易混淆,我拆开说清楚。

#

先纠正一个常见误解:Docker Engine 内部本来就用的是 containerd(从 Docker 17.06 开始)。架构大概是:

docker CLI
   ↓
dockerd (Docker 守护进程,提供 build/push/compose 等高层功能)
   ↓
containerd (负责真正拉镜像、创建/管理容器生命周期)
   ↓
containerd-shim → runc (真正启动容器进程)

也就是说 containerd 一直都在,只是 Docker 在它上面包了一层更友好的 CLI 和一堆高层功能(镜像构建、compose、网络管理、卷管理的易用封装等)。

K8s 从 1.24 开始移除了 dockershim,直接让 kubelet 通过 CRI(Container Runtime Interface)跟 containerd(或 CRI-O)对话,跳过了 dockerd 这一层,这也是为什么你的 CentOS 7 集群(k8s 1.28.2)节点上跑的是纯 containerd,而不是完整的 Docker Engine。

#crictl 不是 docker 的替代品,是调试工具

crictl 是 Kubernetes 社区维护的 CLI,专门用来调试 CRI 兼容的运行时(containerd、CRI-O 都能用),官方文档明确写着它是给 kubelet 调试用的,不建议用来做日常容器管理,原因是:

  • 没有 docker build——crictl 完全不能构建镜像
  • 没有 docker-compose 概念,没有网络/卷的完整管理能力
  • 面向的是 Pod/Sandbox 概念,而不是 Docker 的单容器模型,命令语义和 docker 不完全对应

命令对比举例:

# docker
docker images
docker ps
docker pull nginx
docker exec -it <container> bash
docker logs <container>

# crictl(注意:很多操作范围更受限,且概念是 pod sandbox)
crictl images
crictl ps
crictl pull nginx
crictl exec -it <container-id> sh
crictl logs <container-id>

看着像,但底层模型不同(crictl 里有 pod sandbox 的概念,docker 没有),而且 crictl 完全没有镜像构建能力,只能拉取和查看已有镜像,这也是为什么你之前处理离线镜像时得用 ctr 重打 tag,而不是直接用 crictl 操作。

#如果你想要"像 docker 一样"操作 containerd,真正对应的工具是 nerdctl

nerdctl 是 containerd 社区自己出的 CLI,命令风格几乎和 docker 一模一样,而且支持 buildcomposepush 等完整功能:

nerdctl pull quay.io/xxx
nerdctl build -t myimage .
nerdctl compose up -d
nerdctl images

装法很简单(纯二进制,不依赖 Docker):

curl -sL https://github.com/containerd/nerdctl/releases/download/v2.0.0/nerdctl-2.0.0-linux-amd64.tar.gz | tar -C /usr/local/bin -xz nerdctl

#总结表格

工具 定位 能否替代 docker CLI 日常使用
ctr containerd 原生底层 CLI,极简、面向调试,你之前重打 tag 用的就是它 ❌ 太底层,体验差
crictl CRI 调试工具,给 kubelet/K8s 排障用 ❌ 无构建能力,不是通用场景设计的
nerdctl containerd 社区出的 docker 兼容 CLI ✅ 命令习惯基本无缝迁移,功能对等

回到你的场景:如果是 K8s 集群节点上想调试 Pod/容器状态,crictl 够用;如果是想在没有 Docker Engine 的机器上(比如纯 containerd 的服务器)日常构建、拉取、运行镜像,nerdctl 才是你要的"docker 平替",而不是 crictl