记一次银河麒麟 V11 (OSTree 架构) 下 Docker 启动失败的深度坑

信创,你懂的

现象描述

我在 PVE 虚拟机(实体机没有试过,理论上应该一样的)的银河麒麟 V11 系统中运行 docker run 时,突然遭遇以下报错,容器无法启动:

1
docker run --rm hello-world

结果直接报错了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

docker: Error response from daemon: failed to mount /tmp/containerd-mount1855086 828: mount source: "overlay", target: "/tmp/containerd-mount1855086828", fstype: overlay, flags: 0, data: "workdir=/var/lib/containerd/io.containerd.snapshotter .v1.overlayfs/snapshots/9/work,upperdir=/var/lib/containerd/io.containerd.snapsh otter.v1.overlayfs/snapshots/9/fs,lowerdir=/var/lib/containerd/io.containerd.sna pshotter.v1.overlayfs/snapshots/1/fs,index=off", err: invalid argument



Run 'docker run --help' for more information

```

## 大致原因:存储套娃

### 系统特性

用df命令查看一下

```bash
df -h

结果大致如下

1
2
3
4
5
6
7
8
9
10
11
12
文件系统        大小  已用  可用 已用% 挂载点
tmpfs 795M 19M 776M 3% /run
/dev/sda5 31G 28G 1.6G 95% /
overlay 31G 28G 1.6G 95% /usr
overlay 31G 28G 1.6G 95% /etc
overlay 31G 28G 1.6G 95% /var/lib
tmpfs 3.9G 24M 3.9G 1% /dev/shm
tmpfs 5.0M 8.0K 5.0M 1% /run/lock
/dev/sda1 2.0G 85M 1.8G 5% /boot
/dev/sda6 21G 494M 20G 3% /data
tmpfs 795M 232K 795M 1% /run/user/1000
/dev/sr0 7.7G 7.7G 0 100% /run/media/debian2/Kylin-Desktop-V11

可见该银河麒麟系统采用了类似 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
2
3
sudo mkdir -p /data/docker /data/containerd
sudo systemctl stop docker
sudo systemctl stop containerd

第二步:迁移 Docker 路径

编辑(或创建)/etc/docker/daemon.json

1
2
3
{
"data-root": "/data/docker"
}

注:默认路由为 /var/lib/docker

第三步:迁移 Containerd 路径

编辑 /etc/containerd/config.toml(若没有则新建),修改或添加 root 路径:

修改 root 的值

1
root = "/data/containerd"

注:默认路由为 /var/lib/containerd

第四步:重启服务

1
2
3
sudo systemctl daemon-reload
sudo systemctl start containerd
sudo systemctl start docker

总结与验证

重启后运行 docker info,可以看到:

Docker Root Dir 成功切换到 /data/docker

Storage Driver 恢复为原生的 overlay2(不再报错)

避坑心得:在信创系统或不可变系统(如 Silverblue、OSTree 架构)中部署容器服务时,务必提前通过 df -T 观察 /var/lib 的挂载类型。如果底层已经是 overlay,必须第一时间迁移路径或调整存储驱动!

分别执行以下命令

df -T /var/lib/docker

1
2
3
文件系统       类型      1K的块     已用    可用 已用% 挂载点

overlay overlay 32447272 29177876 1595620 95% /var/lib

df -T /var/lib/containerd

1
2
3
文件系统       类型      1K的块     已用    可用 已用% 挂载点

overlay overlay 32447272 29177984 1595512 95% /var/lib

df -T /data/docker

1
2
文件系统       类型   1K的块   已用     可用 已用% 挂载点
/dev/sda6 ext4 21577900 505040 19951428 3% /data

df -T /data/containerd

1
2
文件系统       类型   1K的块   已用     可用 已用% 挂载点
/dev/sda6 ext4 21577900 505040 19951428 3% /data

可能还有其它错误

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

解决

依次打开 设置->安全中心->安全工具->应用程序执行控制

有两种方法:

  1. 直接关闭

  2. 把相关进程加入管控
    这个没有试,应该操作不太方便

0%