Docker多阶段构建中COPY --from行为异常问题求助
问题:多阶段构建Vite+ReactTS镜像时,prod阶段COPY文件报错
我尝试用单Dockerfile的多阶段构建,搭建Vite+ReactTS的开发、预览(staging)及生产镜像。以下是我的Dockerfile内容:
# # ---- Base Image ---- # 用于设置默认配置 # ARG APP_DIR_PATH=app ARG BASE_IMAGE_VER=20.5.1-alpine3.18 ARG BUILD_PLATFORM=linux/amd64 FROM --platform=${BUILD_PLATFORM} node:${BASE_IMAGE_VER} AS base # 参考node官方镜像最佳实践 RUN apk add --no-cache tini ENTRYPOINT ["/sbin/tini", "--"] WORKDIR /${APP_DIR_PATH} ENV NODE_PM=pnpm RUN npm i -g ${NODE_PM} COPY package.json ./ COPY pnpm-lock.yaml ./ # # ---- Dependencies Image ---- # 用于缓存node_modules(区分生产和开发依赖) # ARG DEV_NODE_MODULES_DIR_PATH=node_modules ARG PROD_NODE_MODULES_DIR_PATH=prod_${DEV_NODE_MODULES_DIR_PATH} FROM base AS dependencies RUN ${NODE_PM} i -P # 可能不需要单独复制生产依赖包,因为Vite构建和预览需要的工具都在devDependencies里,暂时先保留 RUN cp -R ./${DEV_NODE_MODULES_DIR_PATH} ./${PROD_NODE_MODULES_DIR_PATH} RUN ${NODE_PM} i # # ---- Development Image ---- # 开发环境使用 # 注意:修改package.json或配置文件后需要重新构建镜像 # ARG VITE_PORT=8080 FROM dependencies AS dev COPY ./ ./ # 绑定src目录(只读) RUN --mount=type=bind,target=./src/,source=./src/,rw=false ENV VITE_PORT=${VITE_PORT} EXPOSE ${VITE_PORT} CMD ["pnpm", "dev"] # # ---- Build Image ---- # 用于生产环境预览 # 注意:修改package.json或配置文件后需要重新构建镜像 # ARG BUILD_DIR_PATH=dist FROM dev AS build ENV NODE_ENV=production COPY ./ ./ RUN ${NODE_PM} build --outDir ./${BUILD_DIR_PATH} CMD ["pnpm", "preview", "--port", "${VITE_PORT}"] # # ---- Production Image ---- # 生产环境使用 # 注意:代码变更后需要重新构建镜像 # FROM --platform=${BUILD_PLATFORM} nginx:1.25.2-alpine AS prod WORKDIR / COPY ./.configs/nginx/nginx.conf /etc/nginx/nginx.conf RUN rm -rf /usr/share/nginx/html/* COPY --from=build /app/dist /usr/share/nginx/html/ EXPOSE 80 443 CMD ["nginx", "-g", "daemon off;"]
但构建prod阶段时,执行COPY --from=build /app/dist /usr/share/nginx/html/指令始终报错,错误信息如下:
=> ERROR [prod 4/5] COPY --from=build /app/dist /usr/share/nginx/html/ 0.0s ------ > [prod 4/5] COPY --from=build /app/dist /usr/share/nginx/html/: ------ build.Dockerfile:85 -------------------- 83 | RUN rm -rf /usr/share/nginx/html/* 84 | 85 | >>> COPY --from=build /app/dist /usr/share/nginx/html/ 86 | 87 | EXPOSE 80 443 -------------------- ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref 122aaccf-8f31-4e47-aff8-56e3d80edefb::zni94o6alhuq2gp7tryq3q8t0: failed to walk /var/lib/docker/tmp/buildkit-mount959429879/app: lstat /var/lib/docker/tmp/buildkit-mount959429879/app: no such file or directory
我使用的是Windows系统上的Docker v24.0.5,暂未在Stack Overflow找到相关解决方案。
解决方案
问题根源
错误提示/app目录不存在,核心原因有两点:
- dev阶段的
RUN --mount=type=bind指令无效——该指令是BuildKit的构建时临时挂载,镜像构建完成后不会保留,且你已经通过COPY ./ ./把所有代码复制到镜像中,这个挂载完全多余,反而可能干扰BuildKit的缓存逻辑。 - build阶段重复执行
COPY ./ ./,加上缓存机制的影响,可能导致构建产物/app/dist未正确生成,或者路径引用出现异常。
修复步骤
- 移除无效的挂载指令:删除dev阶段的
RUN --mount=type=bind,target=./src/,source=./src/,rw=false行,这行代码对镜像构建没有实际作用。 - 去掉build阶段重复的COPY操作:dev阶段已经完成了代码复制,build阶段无需再次执行
COPY ./ ./,直接运行构建命令即可。 - 排查缓存问题:构建时添加
--no-cache参数,强制清空缓存重新构建,排除缓存导致的路径异常:docker build --no-cache -t your-image-tag . - 确认构建上下文:确保在项目根目录执行构建命令,根目录下必须包含
package.json、pnpm-lock.yaml、src等必要文件,否则COPY指令会失败,间接导致build阶段无法生成dist目录。
修复后的关键代码片段
# ---- Development Image ---- ARG VITE_PORT=8080 FROM dependencies AS dev COPY ./ ./ ENV VITE_PORT=${VITE_PORT} EXPOSE ${VITE_PORT} CMD ["pnpm", "dev"] # ---- Build Image ---- ARG BUILD_DIR_PATH=dist FROM dev AS build ENV NODE_ENV=production # 移除重复的COPY操作,直接执行构建 RUN ${NODE_PM} build --outDir ./${BUILD_DIR_PATH} CMD ["pnpm", "preview", "--port", "${VITE_PORT}"]
额外建议
- 在build阶段添加产物检查指令,方便排查构建是否成功生成dist目录:
RUN ls -la ./${BUILD_DIR_PATH} - 多阶段构建中尽量减少重复操作,利用阶段继承复用文件,提升构建效率。
内容的提问来源于stack exchange,提问作者b442
相关产品推荐
相关产品推荐

