Failed to Extract Layer
Errors
bash
FATA[0006] failed to extract layer sha256:d2d4d2c16a00dd998866a33049d4a1801ba34b719f377ffdf3ec7ae78c9b03eb: lstat /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/566/fs/var/cache/dnf/update-e8b0d229956b0b0b: not a directory: unknown
Dockerfile
bash
FROM docker-hub.foobar.work/foobar-prod/openeuler:22.03-lts-sp2
WORKDIR /app
RUN mkdir -p /etc/nginx/html/foobar/
RUN rm -rf /var/cache/dnf/*
RUN sed -i 's|http://repo.openeuler.org/|https://mirrors.huaweicloud.com/openeuler/|g' /etc/yum.repos.d/openEuler.repo && yum clean all -y && dnf clean all -y
RUN yum update -y && yum install -y nginx libXau
RUN mkdir -p /etc/nginx/html/foobar/
COPY dist /etc/nginx/html/foobar
使用 nerdctl
(基于 containerd
)时报错,而 docker
没问题,通常是因为 Docker 和 containerd 处理文件系统(snapshotter)方式不同。
1. 主要区别:overlayfs 处理方式不同
- Docker 默认使用
overlay2
作为存储驱动,对rm -rf
的兼容性较好。 - containerd(nerdctl)默认使用
overlayfs
作为 snapshotter,在某些情况下,rm -rf
可能会破坏dnf
依赖的目录结构,导致lstat
失败。
影响:
dnf
可能在/var/cache/dnf/update-*
目录创建了符号链接或特殊 inode,直接rm -rf
可能会让 containerd 误认为 某个目录已损坏或变成非法文件。- Docker 的
overlay2
可能对这个情况做了额外的处理,所以不会报错。
containerd 的 overlayfs 可能会在某些情况下导致 lstat
失败,表现为:
bash
lstat /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/XXX/fs/var/cache/dnf/update-*: not a directory: unknown
2. 解决方案
方法 1:避免 rm -rf /var/cache/dnf/*
把 rm -rf /var/cache/dnf/*
替换为官方推荐的 dnf clean all
:
bash
RUN dnf clean all
或者:
bash
RUN yum clean all -y && rm -rf /var/cache/dnf
dnf clean all
会正确清理缓存文件,而不会误删关键目录。
方法 2:强制 containerd 使用 overlay2
如果你的 containerd
运行时允许,你可以尝试强制使用 overlay2
作为 snapshotter:
bash
sudo systemctl stop containerd
sudo sed -i 's/overlayfs/overlay2/' /etc/containerd/config.toml
sudo systemctl restart containerd
然后重新构建镜像:
bash
nerdctl build -t my-nginx-image .
WARNING
overlay2 可能并不是所有 containerd 版本的默认选项,请检查 containerd config.toml 是否支持。
方法 3:使用 devicemapper
作为 snapshotter
如果 overlay2
方案不可行,可以改用 devicemapper
:
bash
sudo sed -i 's/overlayfs/devmapper/' /etc/containerd/config.toml
sudo systemctl restart containerd
3. 结论
- Docker(overlay2)可以容忍
rm -rf
误删目录,但containerd
(overlayfs)可能不行。 - 最好的做法是避免
rm -rf /var/cache/dnf/*
,用dnf clean all
替代。 - 如果你必须用
rm -rf
,可以尝试改用overlay2
或devicemapper
作为 containerd 的 snapshotter。 - 在
containerd
中,dnf
运行时可能会依赖/var/cache/dnf/
结构,删除后会导致lstat
失败。
建议你先尝试 方法 1(改用 dnf clean all
),如果仍然有问题,再考虑切换 snapshotter
(方法 2 或 3)。