Kubernetes Secrets传入React容器后未被create-react-app项目正常读取
问题根因
create-react-app 框架设计中,所有REACT_APP_前缀的环境变量仅**在构建阶段(即执行yarn build/npm run build时)**会被webpack编译注入到最终的静态JS/CSS产物中,属于构建时固定值,不会在应用运行时动态读取容器的系统环境变量。
你当前的Dockerfile在镜像构建阶段就执行了RUN yarn build,此时Kubernetes的Secret还未注入(Secret是容器启动时才会注入到运行环境的),因此打包出来的静态产物中自然没有对应的变量值,后续容器运行时再注入环境变量也不会生效,这就是你进入容器能echo到变量、但React应用读不到的核心原因。
可行解决方案
方案1:构建阶段传入环境变量(适合变量固定无多环境差异场景)
如果你的Secret值不需要随部署环境动态调整,可以在CI/CD构建镜像的阶段就将变量传入构建流程,直接打包到产物中。缺点是不同环境需要构建不同镜像,灵活度低。
方案2:运行时替换静态资源占位符(最适配Kubernetes动态注入Secret场景,生产环境推荐)
这是当前行业内处理前端应用运行时环境变量的主流方案,操作步骤如下:
- 在项目
public目录下新增config.js文件,写入占位内容:
window.RUNTIME_CONFIG = { REACT_APP_DOCS_SERVER_URL: '%%REACT_APP_DOCS_SERVER_URL%%', REACT_APP_AUTH0_CLIENT_ID: '%%REACT_APP_AUTH0_CLIENT_ID%%', REACT_APP_AUTH0_DOMAIN: '%%REACT_APP_AUTH0_DOMAIN%%' }
- 在
public/index.html的<head>标签最顶部引入该配置文件:
<script src="%PUBLIC_URL%/config.js"></script>
- 项目代码中所有读取环境变量的位置,将
process.env.XXX替换为window.RUNTIME_CONFIG.XXX - 新增容器启动脚本
entrypoint.sh放在项目根目录:
#!/bin/sh # 替换静态配置文件中的占位符为真实环境变量 envsubst < /usr/src/app/build/config.js > /usr/src/app/build/config.js.tmp mv /usr/src/app/build/config.js.tmp /usr/src/app/build/config.js # 启动前端服务 exec yarn prod
- 修改Dockerfile,新增脚本复制、赋权逻辑,替换启动命令:
FROM node:17.0.1-alpine3.12 RUN mkdir -p /usr/src/app WORKDIR /usr/src/app # 安装envsubst依赖,alpine镜像默认没有该工具 RUN apk add --no-cache gettext # latest yarn RUN npm i -g --force yarn serve COPY package.json yarn.lock . RUN yarn --frozen-lockfile # Legacy docker settings cos node 17 breaks build ENV NODE_OPTIONS=--openssl-legacy-provider COPY . . RUN yarn build # 复制启动脚本并赋予执行权限 COPY entrypoint.sh . RUN chmod +x entrypoint.sh ENV NODE_ENV=production EXPOSE 3000 CMD ["./entrypoint.sh"]
该方案只需构建一份镜像,不同环境部署时Kubernetes注入对应Secret,容器启动时会自动替换配置文件内容,完全满足动态注入需求。
方案3:容器启动时执行构建(不推荐生产使用)
将Dockerfile中的RUN yarn build删除,修改启动命令为先执行构建再启动服务,缺点是容器启动速度极慢,且镜像包含源码存在安全风险,仅适合临时测试使用。
内容的提问来源于stack exchange,提问作者Marcus Teh
相关产品推荐
相关产品推荐

