Skip to content

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,可以尝试改用 overlay2devicemapper 作为 containerd 的 snapshotter
  • containerd 中,dnf 运行时可能会依赖 /var/cache/dnf/ 结构,删除后会导致 lstat 失败

建议你先尝试 方法 1(改用 dnf clean all),如果仍然有问题,再考虑切换 snapshotter(方法 2 或 3)。