现象描述
我在 PVE 虚拟机(实体机没有试过,理论上应该一样的)的银河麒麟 V11 系统中运行 docker run 时,突然遭遇以下报错,容器无法启动:
1 | docker run --rm hello-world |
结果直接报错了
1 |
|
结果大致如下
1 | 文件系统 大小 已用 可用 已用% 挂载点 |
可见该银河麒麟系统采用了类似 OSTree 的只读不可变设计,通过 overlayfs 把 /usr、/etc 和 /var/lib 挂载在根目录下。
内核冲突
Docker 和 Containerd 默认会在 /var/lib/docker 和 /var/lib/containerd 中使用 overlay2 存储驱动。当它们尝试在已经是 overlay 的系统分区上再次挂载 overlay 时,触发了 Linux 内核的防嵌套保护,直接拒绝并抛出 invalid argument。
解决方法
理论上把docker和containerd的默认数据文件夹改到非overlay的分区就可以了,这样就避开了 Overlay 嵌套
如系统分配的/data挂载点
第一步:创建新目录并停止服务
1 | sudo mkdir -p /data/docker /data/containerd |
第二步:迁移 Docker 路径
编辑(或创建)/etc/docker/daemon.json
1 | { |
注:默认路由为 /var/lib/docker
第三步:迁移 Containerd 路径
编辑 /etc/containerd/config.toml(若没有则新建),修改或添加 root 路径:
修改 root 的值1
root = "/data/containerd"
注:默认路由为 /var/lib/containerd
第四步:重启服务
1 | sudo systemctl daemon-reload |
总结与验证
重启后运行 docker info,可以看到:
Docker Root Dir 成功切换到 /data/docker
Storage Driver 恢复为原生的 overlay2(不再报错)
避坑心得:在信创系统或不可变系统(如 Silverblue、OSTree 架构)中部署容器服务时,务必提前通过 df -T 观察 /var/lib 的挂载类型。如果底层已经是 overlay,必须第一时间迁移路径或调整存储驱动!
分别执行以下命令
df -T /var/lib/docker1
2
3文件系统 类型 1K的块 已用 可用 已用% 挂载点
overlay overlay 32447272 29177876 1595620 95% /var/lib
df -T /var/lib/containerd1
2
3文件系统 类型 1K的块 已用 可用 已用% 挂载点
overlay overlay 32447272 29177984 1595512 95% /var/lib
df -T /data/docker1
2文件系统 类型 1K的块 已用 可用 已用% 挂载点
/dev/sda6 ext4 21577900 505040 19951428 3% /data
df -T /data/containerd
1 | 文件系统 类型 1K的块 已用 可用 已用% 挂载点 |
可能还有其它错误
1 | docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: unable to start init: fork/exec /proc/self/fd/6: operation not permitted |
解决
依次打开 设置->安全中心->安全工具->应用程序执行控制
有两种方法:
直接关闭
把相关进程加入管控
这个没有试,应该操作不太方便