Dockerfile克隆仓库后COPY指令失败,求助排查问题
我来帮你理清楚这个问题——你遇到的矛盾现象其实是Docker构建机制的一个常见坑:
核心原因:COPY指令的工作逻辑你搞混了
COPY指令是从你执行docker build命令的本地目录(也就是「构建上下文」)复制文件到容器内部,而不是在容器的文件系统内部复制文件。
你在RUN git clone步骤里,是在容器内部的/usr/src/app目录下克隆了wait-for-it仓库,所以用RUN ls能看到这个目录(因为这是在容器内部执行的命令)。但最后一行的COPY wait-for-it /usr/src/app是让Docker去你的本地机器上找wait-for-it文件夹,而你本地并没有这个文件夹,自然会报「文件不存在」的错误。
解决办法:直接在容器内部处理文件,不用COPY
既然你已经在容器里克隆了仓库,完全不需要再用COPY指令。根据你的需求,有两种处理方式:
如果只需要仓库里的脚本(比如wait-for-it.sh)
可以在克隆后直接把需要的文件复制到目标目录,同时删除多余的克隆文件夹来减少镜像体积:FROM node:11-alpine RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY ./package.json /usr/src/app/ RUN apk --no-cache --virtual build-dependencies add git python make g++ curl bash \ && git config --global url."https://".insteadOf git:// \ && git clone https://github.com/vishnubob/wait-for-it.git \ && cp wait-for-it/wait-for-it.sh /usr/src/app/ \ && rm -rf wait-for-it \ # 移除克隆的目录,节省空间 && yarn install \ && yarn cache clean --force \ && apk del build-dependencies # 删掉原来的COPY指令如果需要整个wait-for-it目录留在容器里
那你连复制都不用做——因为git clone是在WORKDIR /usr/src/app下执行的,克隆出来的wait-for-it目录本来就已经在/usr/src/app里了,直接删掉最后那行错误的COPY指令就行。
额外优化建议
你原来的RUN指令里重复执行了apk add git curl bash,其实可以把这些依赖合并到前面的build-dependencies安装命令里,减少Docker镜像的分层,让构建更高效(就像上面示例里那样)。
内容的提问来源于stack exchange,提问作者lucas rodriguez

