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

多阶段构建Reactjs_Nginx的builder阶段无法读取环境变量

问题

我用Docker Compose搭建了Django+Nginx+Reactjs_Nginx技术栈,Django和Nginx都能正常读取.env里的环境变量,但Reactjs_Nginx不行。本地跑React时,代码const hostName = process.env.REACT_APP_BACKEND_HOST || "http://localhost:8000/";能正常读环境变量,执行npm run build后用npx serve -s运行也没问题。但docker-compose up --build之后,进入reactjs_nginx容器执行printenv能看到需要的环境变量,可为什么builder阶段读不到环境变量?

对应的Dockerfile:

FROM node:16.15-alpine AS builder
ENV NODE_ENV production
WORKDIR /app
COPY package* /app/
RUN npm install --only=production
COPY . .
RUN npm run build

FROM nginx:1.21.0-alpine as production
ENV NODE_ENV production
COPY --from=builder  /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
CMD ["nginx", "-g", "daemon off;"]

对应的docker-compose.yml:

version: '3.9'

services:
  backend:
    build: 
      context: ./backend
      dockerfile: ./docker/django/Dockerfile
    env_file:
      - .env
    command: gunicorn resume_builder.wsgi -w ${GUNICORN_WORKER_COUNT} -b 0.0.0.0:${DJANGO_PORT}
    networks:
      - resume_builder_network

  backend_nginx:
    build: ./backend/docker/nginx
    volumes:
      - ./backend/docker/nginx/templates:/etc/nginx/templates
    ports: 
      - "${BACKEND_PORT}:${BACKEND_PORT}"
    env_file:
      - .env
    networks:
      - resume_builder_network
    depends_on:
      - backend

  frontend:
    build: 
      context: ./frontend
      target: production
    env_file:
      - .env
    ports:
      - ${FRONTEND_PORT}:${FRONTEND_PORT}
    networks:
      - resume_builder_network

networks:
  resume_builder_network:
原因分析

核心问题很明确:你在docker-compose.yml里给frontend服务配置的env_file,只会把环境变量注入到容器运行阶段,完全不会传递到Docker镜像的构建阶段(也就是builder阶段)。

React的环境变量是在npm run build时就被静态打包进构建产物里的,这个过程正好发生在Docker的builder阶段——此时env_file里的变量还没被注入,自然读不到。而你进容器后能看到变量,是因为那是容器运行时的环境变量,和构建阶段根本没关系。

解决方案

方法1:通过构建参数传递(最常用)

修改docker-compose.yml的frontend服务,添加build.args来传递构建阶段需要的变量:

frontend:
  build: 
    context: ./frontend
    target: production
    args:
      - REACT_APP_BACKEND_HOST=${REACT_APP_BACKEND_HOST}
  env_file:
    - .env
  ports:
    - ${FRONTEND_PORT}:${FRONTEND_PORT}
  networks:
    - resume_builder_network

然后修改Dockerfile的builder阶段,接收并设置这个参数为环境变量:

FROM node:16.15-alpine AS builder
ARG REACT_APP_BACKEND_HOST  # 接收构建参数
ENV REACT_APP_BACKEND_HOST=$REACT_APP_BACKEND_HOST  # 转为环境变量供build使用
ENV NODE_ENV production
WORKDIR /app
COPY package* /app/
RUN npm install --only=production
COPY . .
RUN npm run build

FROM nginx:1.21.0-alpine as production
ENV NODE_ENV production
COPY --from=builder  /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
CMD ["nginx", "-g", "daemon off;"]

方法2:临时构建时直接传参(测试用)

如果只是临时测试,不需要修改配置文件,可以直接在构建命令里指定变量:

REACT_APP_BACKEND_HOST=http://your-backend-host docker-compose build frontend

方法3:用.env文件给构建阶段传参(Docker 17.06+支持)

在frontend目录下创建.env.build文件,写入需要的变量:

REACT_APP_BACKEND_HOST=http://your-backend-host

修改Dockerfile头部启用BuildKit,然后挂载这个文件:

# syntax=docker/dockerfile:1.2
FROM node:16.15-alpine AS builder
ENV NODE_ENV production
WORKDIR /app
COPY package* /app/
RUN npm install --only=production
COPY . .
# 挂载.env.build文件供build使用
RUN --mount=type=secret,id=env,target=/app/.env.build npm run build

FROM nginx:1.21.0-alpine as production
ENV NODE_ENV production
COPY --from=builder  /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
CMD ["nginx", "-g", "daemon off;"]

最后在docker-compose.yml中添加secret配置:

services:
  frontend:
    build: 
      context: ./frontend
      target: production
      secrets:
        - env
    # 其他原有配置不变
secrets:
  env:
    file: ./frontend/.env.build

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:50:22