You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker多阶段构建中COPY --from指令报cannot copy to non-directory错误求助

Docker多阶段构建中COPY --from指令报cannot copy to non-directory错误求助

看起来你遇到的这个问题大概率是目标路径的类型冲突或者Docker BuildKit的行为变化导致的,我来帮你拆解排查一下:

先搞懂报错的本质

错误提示cannot copy to non-directory的核心意思是:你要复制的内容(源)是一个目录,但你指定的目标路径在当前构建阶段已经是一个文件,Docker没办法把目录复制到文件里,所以触发报错。

从你的错误路径/var/lib/buildkit/runc-overlayfs/cachemounts/buildkit3355209005/bin来看,问题应该出在/bin这个路径上——当前构建镜像里的/bin被识别成了文件,而非正常的目录。

具体排查步骤

  1. 检查当前构建阶段的目标路径状态
    在你的COPY命令之前,加一行调试命令,看看目标路径的真实类型:

    # 如果你用的是 COPY --from=sqitch-build /app /
    RUN ls -ld /bin /lib
    # 如果你用的是 COPY --from=sqitch-build /app .
    RUN ls -ld .
    

    执行构建后看输出,如果/bin显示是-rw-r--r--(文件标识)而不是drwxr-xr-x(目录标识),那就是问题根源——肯定是之前的构建步骤不小心把/bin改成了文件(比如误执行了RUN echo xxx > /bin这类命令)。

  2. 检查sqitch-build阶段的/app结构
    在sqitch-build阶段的末尾加调试命令,确认源目录的结构:

    # 在sqitch-build阶段的最后添加
    RUN ls -la /app
    

    确保/app/bin、/app/lib都是目录而非文件。如果/app/bin是文件,当前镜像的/bin是目录,复制整个/app时会把这个文件放到/bin目录下,这没问题;但如果/app/bin是目录,而当前镜像的/bin是文件,就会触发类型冲突报错。

  3. 清理BuildKit缓存试试
    有时候旧的构建缓存会残留异常状态,导致奇怪的报错。执行下面的命令清理缓存后重新构建:

    docker builder prune -af
    
  4. 检查Docker版本变化
    你提到之前正常最近才出问题,有可能是Docker版本更新导致BuildKit的COPY行为更严格了。比如Docker 23.x之后的版本,对源/目标类型的检查更严格,之前可能静默忽略的冲突现在直接报错。可以对比一下之前正常工作时的Docker版本,看看是不是版本更新引发的问题。

关于临时解决方案的补充

你现在用逐个复制子目录的方式能工作,是因为单独指定COPY --from=sqitch-build /app/bin /bin时,Docker会把/app/bin的内容合并到已有的/bin目录里(前提是/bin是目录);而复制整个/app到/时,Docker会尝试把/app下的每个条目直接覆盖到根目录下,如果其中某个条目和根目录下的已有文件类型冲突,就会触发报错。

备注:内容来源于stack exchange,提问作者theory

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 06:28:00