基于Azure DevOps Pipeline构建ReactJS v18多环境通用Docker镜像遇阻
单Docker镜像适配ReactJS v18多环境运行的可行性方案
完全可行,此前团队认为无法实现,大概率是受限于React默认构建时硬编码环境变量的特性,但通过运行时动态注入环境变量的方式,就能实现单一镜像适配dev、QA、预生产、生产等多环境。
核心实现思路
React默认会在构建阶段将process.env.REACT_APP_*这类环境变量编译进静态文件,导致镜像无法动态切换环境。我们需要调整代码逻辑,将环境变量的读取时机从构建阶段推迟到容器启动后的运行阶段。
具体实现步骤
调整React项目配置,避免硬编码环境变量
- 创建全局配置文件,从全局对象读取环境变量,而非直接使用
process.env:// src/config.js export const appConfig = { apiUrl: window.__APP_ENV__.API_URL || 'https://default-api.example.com', env: window.__APP_ENV__.ENVIRONMENT || 'production' }; - 在
public/index.html中添加全局变量占位:<script> window.__APP_ENV__ = { API_URL: '%API_URL%', ENVIRONMENT: '%ENVIRONMENT%' }; </script>
- 创建全局配置文件,从全局对象读取环境变量,而非直接使用
编写支持动态注入的Dockerfile
- 分构建和运行两个阶段,用nginx托管静态文件,同时引入启动脚本处理环境变量替换:
# 构建阶段:生成静态文件 FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # 运行阶段:托管静态文件+动态注入环境变量 FROM nginx:alpine COPY --from=builder /app/build /usr/share/nginx/html COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] CMD ["nginx", "-g", "daemon off;"]
- 分构建和运行两个阶段,用nginx托管静态文件,同时引入启动脚本处理环境变量替换:
编写启动脚本替换占位符
- 用
sed命令在容器启动时,将环境变量值替换到index.html的占位符中:#!/bin/sh # 替换全局配置占位符 sed -i "s|%API_URL%|${API_URL}|g" /usr/share/nginx/html/index.html sed -i "s|%ENVIRONMENT%|${ENVIRONMENT}|g" /usr/share/nginx/html/index.html # 执行原容器启动命令 exec "$@"
- 用
Azure DevOps Pipeline配置
- 构建阶段只需构建单一镜像并推送到镜像仓库,无需传入任何环境变量;
- 部署到不同环境时,通过Azure DevOps的部署任务(如Azure App Service部署、Kubernetes部署)传入对应环境的
API_URL、ENVIRONMENT等变量即可。
优势
- 减少镜像构建次数,降低CI/CD Pipeline的运行时间和资源消耗;
- 镜像一致性更高,避免多环境构建可能带来的差异;
- 环境变量管理更灵活,无需重新构建即可调整配置。
内容的提问来源于stack exchange,提问作者know1995
相关产品推荐
相关产品推荐

