部署在Fargate上的React应用未正确读取REACT_APP_API_URL环境变量
问题原因
React 所有REACT_APP_开头的环境变量仅在构建阶段生效,执行npm run build打包时,变量值会被直接硬编码到生成的静态JS文件中,容器运行阶段新增的环境变量不会对已经打包完成的静态资源生效。
你本地运行容器正常,是因为你构建镜像时已经把本地的REACT_APP_API_URL值打包到了镜像里;而Fargate任务定义中配置的是运行时环境变量,无法修改已经构建完成的镜像内的静态文件内容,代码读取不到环境变量时就会 fallback 到当前页面域名,也就是你的React应用负载均衡地址。
解决方案
方案1:构建镜像时传入环境变量(适合单环境部署)
修改Dockerfile的构建阶段,增加构建参数声明,将构建参数传入为构建阶段的环境变量:
# BUILD IMAGE FROM node:14-alpine as build-stage # 新增构建参数声明 ARG REACT_APP_API_URL # 赋值为环境变量供构建时读取 ENV REACT_APP_API_URL=$REACT_APP_API_URL WORKDIR /app COPY package*.json ./ RUN npm install RUN npm install cross-env -g # 修复原Dockerfile笔误:多余的npm install RUN npm install @craco/craco -g COPY . . RUN npm run build # 后续SERVING阶段保持不变 FROM fitiavana07/nginx-react COPY --from=build-stage /app/build /usr/share/nginx/html EXPOSE 80 CMD nginx -g 'daemon off;'
构建镜像时通过--build-arg传入实际API地址:
docker build --build-arg REACT_APP_API_URL=你的实际API接口前缀 -t 你的镜像名称 .
该方案构建出的镜像已经内置了正确的API地址,Fargate运行时不需要再配置该环境变量。
方案2:运行时动态替换(适合多环境共用同一镜像)
如果需要测试、生产等多环境共用同一个镜像,不需要每个环境单独构建,可以通过启动脚本在容器启动时替换静态文件中的占位符:
- 先修改React代码中调用API的部分,将
process.env.REACT_APP_API_URL替换为自定义占位符,比如__API_URL__ - 修改Dockerfile的启动命令,增加替换逻辑:
# SERVING IMAGE FROM fitiavana07/nginx-react COPY --from=build-stage /app/build /usr/share/nginx/html EXPOSE 80 # 修改启动命令,启动Nginx前替换占位符为运行时环境变量值 CMD ["/bin/sh", "-c", "cd /usr/share/nginx/html && find . -type f -name '*.js' -exec sed -i 's/__API_URL__/$REACT_APP_API_URL/g' {} \; && nginx -g 'daemon off;'"]
该方案可以继续沿用你当前在Fargate任务定义中配置运行时环境变量的逻辑,容器启动时会自动将静态文件中的占位符替换为你配置的实际API地址。
内容的提问来源于stack exchange,提问作者Jeremy
相关产品推荐
相关产品推荐

