Windows下Docker Desktop执行docker build读取错误Dockerfile内容求助
问题描述
我使用Docker已有多年,近日遇到一个十分奇怪的问题:执行docker build命令时,程序读取的并非当前目录下实际存在的Dockerfile内容。
相关执行日志
PS D:\reposNovabase\charmander\charmanderWarehouse> type Dockerfile FROM adoptopenjdk/openjdk11-openj9:jdk-11.0.11_9_openj9-0.26.0-alpine WORKDIR /app COPY build/libs/charmanderWarehouse-1.0.0-SNAPSHOT.jar /app EXPOSE 8083 CMD ["java", "-Xmx70m", "-jar", "charmanderWarehouse-1.0.0-SNAPSHOT.jar"] PS D:\reposNovabase\charmander\charmanderWarehouse> docker build -f Dockerfile -t javiersedano/charmander-warehouse:test1 . [+] Building 0.2s (7/7) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 32B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/adoptopenjdk/openjdk11-openj9:jdk-11.0.11_9_openj9-0.26.0-alpine 0.0s => [1/3] FROM docker.io/adoptopenjdk/openjdk11-openj9:jdk-11.0.11_9_openj9-0.26.0-alpine 0.0s => [internal] load build context 0.0s => => transferring context: 57B 0.0s => CACHED [2/3] WORKDIR /app 0.0s => ERROR [3/3] COPY build/libs/charmanderPurchases-1.0.0-SNAPSHOT.jar /app 0.0s ------ > [3/3] COPY build/libs/charmanderPurchases-1.0.0-SNAPSHOT.jar /app: ------ failed to compute cache key: "/build/libs/charmanderPurchases-1.0.0-SNAPSHOT.jar" not found: not found PS D:\reposNovabase\charmander\charmanderWarehouse>
问题疑点
- 本地Dockerfile中定义的COPY指令为:
COPY build/libs/charmanderWarehouse-1.0.0-SNAPSHOT.jar /app
- 但
docker build执行时却报错提示:
ERROR [3/3] COPY build/libs/charmanderPurchases-1.0.0-SNAPSHOT.jar /app
额外线索
- 报错中提到的charmanderPurchases是同级兄弟项目的jar包名称,该项目的Dockerfile在本次构建前一秒刚刚执行过构建,整个构建流程是批量构建多个镜像的伪CI .cmd脚本的一部分。
- 临时解决方案:如果使用
type Dockerfile | docker build -f - -t javiersedano/charmander-warehouse:test1 .命令执行构建,就可以正常运行;而且执行完该命令后,原来的docker build命令也能正常工作了,但此时兄弟项目的构建就会报错,charmanderPurchases项目的构建会尝试复制charmanderWarehouse的jar包,完全是反过来的情况。 - 环境信息:Windows 10系统,使用WSL2后端的Docker Desktop for Windows 3.6.0版本,升级到4.0.1版本测试问题仍然存在。
问题解答
根因
这是Docker Desktop WSL2后端的已知问题,根源是BuildKit构建缓存的文件标识逻辑和WSL2挂载Windows NTFS分区的inode缓存机制冲突:
BuildKit默认会用文件的inode作为Dockerfile的缓存键,当你在Windows NTFS分区(挂载到WSL2的/mnt/盘符路径下)修改文件时,WSL2不会及时更新对应文件的inode值,导致BuildKit误以为当前目录的Dockerfile和之前构建过的另一个项目的Dockerfile是同一个文件,直接复用了缓存的旧Dockerfile内容,就出现了构建时读取到其他项目Dockerfile的异常情况。
用管道传递Dockerfile内容的方式能生效,是因为这种场景下BuildKit直接读取标准输入的内容,不会用inode做缓存键,每次都读取最新的内容。
排查思路
- 先执行
docker builder prune -f清理所有闲置的构建缓存,再次执行构建命令,如果问题消失就可以确认是构建缓存导致的异常。 - 将同一份Dockerfile复制到WSL2原生的EXT4文件系统路径下(比如WSL内的
/home/你的用户名目录)执行构建,确认是否还会复现问题,如果不复现就可以确认是跨文件系统挂载的缓存问题。
解决方案
临时解决方案(适用于现有脚本快速修复)
- 每次执行
docker build前先执行docker builder prune -f清理构建缓存,避免缓存命中错误。 - 直接修改批量构建脚本,统一用管道传递Dockerfile内容的方式执行构建,绕过文件inode缓存逻辑。
- 也可以在构建命令中添加
--no-cache参数,强制不使用任何构建缓存,不过会拖慢构建速度。
永久解决方案
- 最推荐:将项目代码迁移到WSL2原生文件系统,所有构建操作都在WSL2的EXT4分区下执行,不仅能彻底解决这个缓存问题,还能大幅提升Docker构建的IO性能。
- 如果必须将代码放在Windows NTFS分区,可以在Docker Desktop设置中关闭「Use the WSL 2 based engine」,切换为Hyper-V后端,即可规避该问题,但整体构建性能会有所下降。
- 也可以选择在Docker Desktop的设置中关闭BuildKit,不过会失去BuildKit带来的并行构建、缓存优化等特性,构建速度会变慢。
内容的提问来源于stack exchange,提问作者Javier Sedano
相关产品推荐
相关产品推荐

