一、docker-cli、nerdctl 和 ctr 以及 crictl 介绍
docker
, nerdctl
和 ctr
和 crictl
都是用于容器管理的命令行工具,但它们在设计目的、使用场景和技术栈上有所不同。下面分别对这四个工具进行介绍,并指出它们之间的主要差异。
1.1、Docker CLI
Docker CLI(Command Line Interface) 是 Docker 项目提供的官方命令行工具,广泛应用于基于 Docker 技术的容器管理和操作。用户可以通过它来构建、运行、管理和分发 Docker 容器和镜像。Docker CLI 支持与 Docker daemon 通信,执行如创建容器、执行命令、管理网络、数据卷等操作。它的易用性和全面的功能集使其成为容器技术中最流行的工具之一。
- 特点:用户友好、功能全面,支持广泛的容器管理操作。
- 适用场景:通用的容器开发、部署和管理任务,特别是与 Docker 引擎集成的环境。
1.2、Nerdctl
nerdctl 是一个与 Docker CLI 风格和语义兼容的命令行工具,专为 Containerd 设计。它由 Rancher Labs 开发,旨在为那些熟悉 Docker CLI 使用方式的用户提供一种更加轻量级且与 Containerd 深度集成的管理工具。Nerdctl 使得从 Docker 迁移到 Containerd 成为一个平滑的过程,因为它支持大部分 Docker CLI 的命令和选项,同时利用了 Containerd 的高效和灵活性。
主要特点:
-
Docker CLI 兼容性:nerdctl 的命令和选项设计与 Docker CLI 高度相似,这意味着 Docker 用户可以几乎无缝地切换到使用 nerdctl,无需重新学习大量新命令。
-
轻量级:相比于 Docker,nerdctl 直接与 Containerd 交互,避免了 Docker daemon 的额外资源消耗,适合追求更高性能和更小资源占用的场景。
-
Kubernetes 集成友好:由于 Containerd 是 Kubernetes 默认的容器运行时之一,nerdctl 自然非常适合在 Kubernetes 环境下使用,尤其是对于那些希望保持 CLI 统一性和简化管理流程的用户。
-
增强功能:除了基本的 Docker CLI 兼容功能外,nerdctl 还提供了一些额外的特性和命令,以更好地利用 Containerd 的特性,比如对多平台镜像的支持等。
1.3、Ctr
Ctr 是 Containerd 项目提供的一个轻量级的命令行工具,旨在替代 Docker CLI 在与 Containerd 交互时的角色。Containerd 是一个容器运行时,提供了容器生命周期管理的基础能力,被设计为低层级的系统组件,常作为 Kubernetes 等更高级容器编排系统的底层技术。Ctr 提供了直接管理容器、镜像、沙箱等底层功能,相比 Docker CLI 更加面向底层和系统集成。
- 特点:轻量、底层、面向系统集成,特别适合与 Containerd 配合使用。
- 适用场景:在使用 Containerd 作为容器运行时的环境中,进行更底层的容器管理操作,或在 Kubernetes 等平台中作为后台服务的一部分。
1.4、Crictl
Crictl (CRI Control) 是 Kubernetes 项目的容器运行时接口 (CRI, Container Runtime Interface) 的一个命令行客户端工具。CRI 是 Kubernetes 为了支持多种容器运行时而引入的标准接口,允许 Kubernetes 与不同的容器运行时(如 Docker、Containerd、CRI-O 等)通信。Crictl 专门设计用来与实现了 CRI 接口的容器运行时进行交互,进行容器和 Pod 的管理。
- 特点:专为 Kubernetes 设计,支持多种遵循 CRI 的容器运行时。
- 适用场景:在 Kubernetes 集群中进行容器和 Pod 的调试、监控等操作,特别是在需要跨不同容器运行时标准化管理操作时。
差异总结
- 目标用户和场景 :
- Docker CLI 面向更广泛的用户群体,特别是那些直接与 Docker 引擎交互的开发者和运维人员;
- Ctr 更适用于与 Containerd 集成的底层操作和系统级管理;
- Crictl 则聚焦于 Kubernetes 环境下的容器管理,提供跨容器运行时的一致性操作。
- 功能和深度 :
- Docker CLI 功能最为全面,覆盖了从构建到部署的整个容器生命周期;
- Ctr 和 Crictl 更专注于底层容器操作,其中 Crictl 通过 CRI 标准化了与容器运行时的交互。
- 集成与生态系统 :
- Docker CLI 与 Docker 生态紧密集成;
- Ctr 与 Containerd(及背后的 CNCF 生态)相辅相成;
- Crictl 是 Kubernetes 生态中的一部分,特别适合云原生应用的管理。
二、命令对比
命令描述 | docker | nerdctl | ctr | crictl |
---|---|---|---|---|
显示正在运行的容器 | docker ps |
nerdctl ps |
ctr task ls ctr containers ls |
crictl ps |
显示所有的容器(包含退出等) | docker ps -a |
nerdctl ps -a |
- | crictl ps -a |
仅显示容器id | docker ps -q |
nerdctl ps -q |
ctr containers ls -q |
crictl ps -q |
启动容器 | docker run |
nerdctl run |
ctr run |
crictl run |
进入容器 | docker exec |
nerdctl exec |
- | crictl exec |
停止容器 | docker stop |
nerdctl stop |
ctr pause |
- |
删除容器 | docker rm |
nerdctl rm |
ctr task rm |
- |
强制删除 | docker rm -f |
nerdctl rm -f |
ctr task rm -f |
- |
删除退出状态的所有容器 | docker container prune |
nerdctl container prune |
- | - |
copy 文件 | docker cp |
nerdctl cp |
- | - |
查看日志 | docker logs |
nerdctl logs |
- | crictl logs |
查看容器/镜像元信息 | docker inspect |
nerdctl inspect |
- | crictl inspect/inspecti |
查看版本 | docker version |
nerdctl version |
ctr version |
crictl version |
查看系统级信息 | docker info |
nerdctl info |
- | crictl info |
下载镜像 | docker pull |
nerdctl pull |
ctr images pull |
crictl pull |
删除镜像 | docker rmi |
nerdctl rmi |
ctr image rm |
crictl rmi |
查看镜像列表 | docker images |
nerdctl images |
ctr image ls |
crictl images |
镜像tag | docker tag |
nerdctl tag |
ctr image tag |
- |
镜像仓库登录 | docker login |
nerdctl login |
- | - |
镜像仓库登出 | docker logout |
nerdctl logout |
- | - |
包方式导入镜像 | docker load -i docker import |
nerdctl load -i nerdctl import |
-/ctr image import |
- |
包方式导出镜像 | dcoker save -o docker export |
nerdctl save -o |
ctr image export |
- |
镜像label | docker label |
- | ctr image label |
- |
镜像push | docker push |
nerdctl push |
ctr image push |
- |
镜像构建 | docker build |
nerdctl build |
- | - |
三、具体差异
3.1、docker ps -q & nerdctl ps -q & ctr containers ls -q & crictl ps -q 显示的是所有容器的id,还是仅是正在运行容器的ID
docker
shell
$ docker ps | wc -l
3 # 包含首行,实际为2
$ docker ps -a | wc -l
8
$ docker ps -q | wc -l
2
docker ps -q 显示的是正在运行的
nerdctl
shell
$ nerdctl ps | wc -l
29
$ nerdctl ps -a | wc -l
94
$ nerdctl ps -q | wc -l
28
crictl
shell
$ crictl ps | wc -l
15
$ crictl ps -a | wc -l
33
$ crictl ps -q | wc -l
14
综上:
docker、nerdctl 和crictl 均是显示正在运行的容器id,ctr 没有-a 命令
3.2 指定运行时 sock
docker
, nerdctl
, ctr
, 和 crictl
这四个命令行工具在与容器运行时(如 Containerd)交互时,对于指定运行时socket(通常为containerd.sock)的方式存在一些差异,这主要是由于它们的设计目的、使用场景以及与底层容器运行时的集成方式不同所致。下面分别说明它们的差异:
Docker
- 默认配置:Docker 有自己的守护进程(daemon),默认情况下,Docker 客户端会连接到本地的 Docker 守护进程,而不是直接与 Containerd 交互。Docker 守护进程自身负责与容器运行时(可能是 Docker 自带的或其他,如Containerd)的通信。
- Socket配置 :Docker 守护进程的socket位置通常是固定的(例如,在Linux上通常是
/var/run/docker.sock
),用户通常不需要直接指定socket地址。
Nerdctl
- 设计目的:Nerdctl 是为了提供一个与 Docker CLI 风格和功能相匹配的工具,专为 Containerd 设计。它直接与 Containerd 交互,模仿 Docker CLI 的使用体验。
- Socket配置 :默认情况下,nerdctl 会查找 Containerd 的默认 socket 位置(通常是
/run/containerd/containerd.sock
)。如果修改了containerd.sock路径,可以通过环境变量或如下命令行参数指定不同的socket,例如:
shell
nerdctl --address /path/to/containerd.sock ps
Ctr
-
定位:Ctr 是 Containerd 自带的低级别命令行工具,主要用于调试和直接管理 Containerd。它提供了更底层的控制能力。
-
Socket配置 :Ctr 也默认查找
/run/containerd/containerd.sock
,但可以通过-a
或--address
参数显式指定socket位置,例如:bashctr -a /path/to/containerd.sock containers ls
Crictl
-
Kubernetes集成:Crictl 是为 Kubernetes 与 CRI 兼容的容器运行时(包括 Containerd)设计的。它通过 CRI 接口与运行时通信,主要用于 Kubernetes 环境下的容器管理。
-
Socket配置 :Crictl 通常通过环境变量或配置文件(如
/etc/crictl.yaml
)来指定运行时socket,而不是每次执行命令时都指定。例如,在配置文件中,你可以设置runtime-endpoint
来指定 Containerd 的socket地址。shell$ cat /etc/crictl.yaml runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock
3.3 run 命令参数差异
参数 | docker run | nerdctl run | ctr run | crictl run |
---|---|---|---|---|
-i | ✅ | ✅ | ✅ | ❌ |
-t | ✅ | ✅ | ✅ | ❌ |
-d | ✅ | ✅ | ✅ | ❌ |
-it | ✅ | ✅ | ❌ | ❌ |
-itd | ✅ | ❌ | ❌ | ❌ |
--env | ✅ | ✅ | ✅ | ❌ |
--network | ✅ | ✅ | ❌ | ❌ |
--name | ✅ | ✅ | ❌ | ❌ |
3.4 覆盖或指定 entrypoint 差异
docker run
允许你通过 --entrypoint
参数覆盖镜像中定义的 ENTRYPOINT
。如果你提供了这个参数,指定的命令将会替代镜像中的 ENTRYPOINT
,并且可以结合命令参数。例如,docker run --entrypoint "/bin/bash" myimage
将使用 /bin/bash
作为容器的入口点。
nerdctl run
设计上力求与 Docker CLI
兼容,因此它也支持 --entrypoint
参数来覆盖镜像的默认入口点。用法与 docker run 相似,允许你自定义容器启动时执行的第一个命令或脚本。
ctr run
的命令行参数较为基础,它没有直接提供一个等同于 --entrypoint 的参数 来轻松覆盖镜像的 ENTRYPOINT。通常,你需要通过直接指定命令来间接改变入口点行为,这意味着你输入的命令会替代镜像的默认 ENTRYPOINT 和 CMD
。
crictl 命令行工具并不直接提供 run 命令来启动独立容器,因为它主要针对 Kubernetes 环境下的容器管理。在 Kubernetes 中,容器的启动配置是通过 Pod 的定义(YAML 文件)来完成的,其中包括 command
和 args
字段,它们分别对应于镜像的 ENTRYPOINT
和 CMD
。这意味着,++你不是通过 crictl 直接指定 entrypoint,而是通过修改 Pod 配置文件来达到目的。++
3.5 都各自支持哪些类型的shell?
支持哪些shell 不由命令行决定,由镜像决定
/etc/shells展示了系统支持哪些shell
shell
$ cat /etc/shells
/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
如下方式可以查看机器默认的shell
shell
$ echo $SHELL
/bin/bash
$ cat /etc/passwd
username:x:UID:GID:User Info:/home/username:/bin/bash
3.6 ctr 和crictl 如何实现docker login
功能
ctr 和 crictl 并没有像docker login
这样直接管理registry权限的命令;ctr 用containerd的配置文件 /etc/containerd/config.toml
来存储账号密码,示例如下:
shell
[plugins."io.containerd.grpc.v1.cri".registry.configs."https://index.docker.io/v1/"]
auth = "YOUR_AUTH_TOKEN"
username = "YOUR_USERNAME"
crictl 通常与 Kubernetes 集群一起使用,而 Kubernetes 集群的镜像拉取认证信息是通过集群内的服务账户(ServiceAccount)或 ImagePullSecrets 来管理的,而不是直接通过 crictl 登录。但如果你需要在没有 Kubernetes 环境下使用 crictl 与私有 registry 交互,可能需要通过相应 registry
的认证令牌或证书来配置,这与上面一致了。
另外。还可以通过创建secret
来实现使用docker的配置文件~/.docker/config.json
,如下:
https://kkgithub.com/containerd/containerd/blob/main/vendor/k8s.io/api/core/v1/types.go
go
// SecretTypeDockerConfigJson contains a dockercfg file that follows the same format rules as ~/.docker/config.json
//
// Required fields:
// - Secret.Data[".dockerconfigjson"] - a serialized ~/.docker/config.json file
SecretTypeDockerConfigJson SecretType = "kubernetes.io/dockerconfigjson"
参考文档
1、https://kkgithub.com/containerd/containerd/blob/main/cmd/ctr/main.go
2、https://kkgithub.com/docker/cli/blob/master/README.md
3、https://kkgithub.com/containerd/nerdctl
4、https://blog.csdn.net/zfw_666666/article/details/136898245
5、https://www.cnblogs.com/liugp/p/16633732.html
6、https://kkgithub.com/containerd/containerd/blob/main/docs/cri/crictl.md
7、https://kkgithub.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md