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

Docker多阶段构建:如何在COPY命令中使用文件变量?

解决Docker多阶段构建中读取环境变量用于COPY指令的问题

问题根源

Docker的RUN指令在独立的shell进程中执行,指令内导出的环境变量仅对当前进程有效,无法被后续的COPY等构建指令访问——因为COPY是由Docker引擎直接处理的,不依赖容器内的shell环境。你当前的写法中,RUN export PROJECT_NAME=...设置的变量无法传递给下一行的COPY。

最优解决方案

方案1:在Build阶段将产物移到固定路径(推荐)

直接在Build阶段把Angular构建产物复制到一个固定路径,避免后续依赖变量,这种方式最简单可靠:

FROM node:16-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci    
# 提取项目名称时去掉npm返回的双引号
RUN echo "PROJECT_NAME=$(npm pkg get name | tr -d '"')" >> /tmp/project.env
RUN echo "PROJECT_VERSION=$(npm pkg get version | tr -d '"')" >> /tmp/project.env    
COPY . .
RUN npm run build --omit-dev
# 将构建产物复制到固定路径,消除变量依赖
RUN PROJECT_NAME=$(npm pkg get name | tr -d '"') && cp -r /app/dist/$PROJECT_NAME /build-dist

FROM nginx:1.23.4-alpine
COPY --from=build /tmp/project.env /tmp/project.env
# 直接复制固定路径的产物
COPY --from=build /build-dist /usr/share/nginx/html
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]

方案2:使用Docker ARG跨阶段传递变量

ARG是Docker的构建阶段变量,可以在多阶段之间传递:

FROM node:16-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci    
# 提取项目名称并写入临时文件
RUN echo "PROJECT_NAME=$(npm pkg get name | tr -d '"')" > /tmp/project-name.txt
RUN echo "PROJECT_VERSION=$(npm pkg get version | tr -d '"')" >> /tmp/project.env    
COPY . .
RUN npm run build --omit-dev

FROM nginx:1.23.4-alpine
# 从Build阶段读取项目名称到当前阶段的ARG
ARG PROJECT_NAME
RUN --mount=from=build,source=/tmp/project-name.txt,target=/tmp/project-name.txt \
    export PROJECT_NAME=$(cat /tmp/project-name.txt | cut -d= -f2) && \
    echo "PROJECT_NAME=$PROJECT_NAME" > /etc/profile.d/project.sh
# 使用ARG变量复制产物
COPY --from=build /app/dist/$PROJECT_NAME /usr/share/nginx/html
COPY --from=build /tmp/project.env /tmp/project.env
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]

额外优化建议

  • 处理npm输出的引号:npm pkg get name会返回带双引号的字符串(如"my-angular-app"),必须用tr -d '"'移除引号,否则会导致路径错误。
  • 固定Angular构建输出路径:直接修改angular.json中项目的outputPath配置为"dist"(默认是"dist/${projectName}"),这样构建后产物直接放在/app/dist下,Dockerfile中无需处理任何变量,直接复制/app/dist即可,这是最简洁的方式。

内容的提问来源于stack exchange,提问作者Starfish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:24:53