为何无法用nerdctl/crictl查看Docker启动的容器?
我使用Docker 20.10.21版本,了解到该版本采用containerd管理镜像和容器生命周期,但无法通过crictl/nerdctl查看Docker CLI启动的容器。
已进行的尝试
- 检查Docker与containerd的关联
执行systemctl status docker得到以下输出:
docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; preset: disabled)
Drop-In: /etc/systemd/system/docker.service.d
└─http-proxy.conf
Active: active (running) since Sun 2022-12-04 22:44:27 CST; 1min 18s ago TriggeredBy: ● docker.socket
Docs: https://docs.docker.com Main PID: 1821 (dockerd)
Tasks: 91 (limit: 38297)
Memory: 229.6M
CPU: 1.214s
CGroup: /system.slice/docker.service
├─1821 /usr/bin/dockerd -H fd://
├─1845 containerd --config /var/run/docker/containerd/containerd.toml --log-level info
由此确认containerd由Docker守护进程启动,Unix套接字路径为/var/run/docker/containerd/containerd.sock。
- 使用nerdctl尝试查看容器
普通用户执行报错:
$ nerdctl --address unix:///var/run/docker/containerd/containerd.sock ps
FATA[0000] rootless containerd not running? (hint: usecontainerd-rootless-setuptool.sh installto start rootless containerd): stat /run/user/1000/containerd-rootless: no such file or directory
使用sudo执行后无结果:
sudo nerdctl --address unix:///var/run/docker/containerd/containerd.sock ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
但docker ps显示有多个正在运行的容器。
- 使用crictl尝试查看容器
执行命令后报错:
sudo crictl --r unix:///var/run/docker/containerd/containerd.sock ps
E1204 22:47:27.190569 3925 remote_runtime.go:557] "ListContainers with filter from runtime service failed" err="rpc error: code = Unimplemented desc = unknown service runtime.v1alpha2.RuntimeService" filter="&ContainerFilter{Id:,State:&ContainerStateValue{State:CONTAINER_RUNNING,},PodSandboxId:,LabelSelector:map[string]string{},}"
FATA[0000] listing containers: rpc error: code = Unimplemented desc = unknown service runtime.v1alpha2.RuntimeService
疑问
为何无法通过nerdctl/crictl得到与Docker CLI相同的容器列表?是操作有误还是理解存在偏差?
核心原因:Docker对containerd的定制化封装
Docker确实依赖containerd作为底层运行时,但它并非直接暴露containerd的标准接口给外部工具,而是通过专属逻辑做了封装,具体问题点如下:
- 命名空间隔离导致nerdctl无结果
Docker启动的containerd实例使用了专属的moby命名空间,而nerdctl默认查询的是default命名空间,这就是你执行sudo nerdctl ... ps看不到容器的直接原因。
要查看Docker启动的容器,需要明确指定命名空间:
sudo nerdctl --address unix:///var/run/docker/containerd/containerd.sock --namespace moby ps
- CRI接口未启用导致crictl报错
crictl是基于Kubernetes容器运行时接口(CRI)开发的工具,但Docker自带的containerd实例默认未启用CRI服务。你看到的unknown service runtime.v1alpha2.RuntimeService报错,本质是containerd没有提供CRI接口支持。
如果非要用crictl访问,需要修改Docker的containerd配置文件/var/run/docker/containerd/containerd.toml,启用CRI插件:
[plugins."io.containerd.grpc.v1.cri"] enable = true
修改后重启Docker服务即可,但这种做法不推荐——Docker本身不需要CRI接口,启用后可能引发兼容性问题。
额外说明:Docker内置containerd vs 独立containerd
你接触的是Docker内置的containerd,它和单独安装的containerd是两个完全独立的实例:
- 内置containerd完全受dockerd管控,配置、命名空间、接口都被Docker定制化;
- 独立安装的containerd是标准的容器运行时,可直接被nerdctl、crictl等工具访问。
如果需要用nerdctl管理容器,建议单独安装containerd,而非直接使用Docker自带的实例。
内容的提问来源于stack exchange,提问作者shizhz

