React应用无法读取Kubernetes Pod中定义的环境变量如何解决?
问题根本原因
你遇到的问题是React单页应用的特性导致的,和Kubernetes本身无关:
- React应用执行
npm run build构建时,react-scripts会将代码中所有process.env.REACT_APP_*变量直接替换为构建阶段当前环境的变量值,硬编码到打包生成的静态JS/HTML文件中,编译完成后的静态资源不存在任何动态读取环境变量的逻辑。 - 你在Dockerfile的构建阶段就已经定义了
REACT_APP_ENV_VARIABLE="It works!",构建时这个值就被直接写到了最终的静态文件里;而构建阶段没有定义REACT_APP_ENV_VARIABLE_TWO,所以这个变量被直接替换为空值。 - 你在Kubernetes Pod中定义的环境变量是注入给Nginx容器进程的运行时环境变量,已经打包完成的静态页面不会读取这些变量,所以你进入容器查环境变量是对的,但页面显示还是旧值。
解决方案
根据你的使用场景可以选择以下两种方案:
方案1:构建时传入环境变量(适合变量固定、不需要运行时修改的场景)
如果你的环境变量不需要在部署时动态修改,可以在构建镜像时传入变量,不用写死在Dockerfile中:
- 修改Dockerfile,将固定ENV改为构建参数:
# 新增构建参数 ARG REACT_APP_ENV_VARIABLE ARG REACT_APP_ENV_VARIABLE_TWO # 转成环境变量供构建时使用 ENV REACT_APP_ENV_VARIABLE=$REACT_APP_ENV_VARIABLE ENV REACT_APP_ENV_VARIABLE_TWO=$REACT_APP_ENV_VARIABLE_TWO
- 构建镜像时传入参数:
docker build --build-arg REACT_APP_ENV_VARIABLE="Variable from Kube!" --build-arg REACT_APP_ENV_VARIABLE_TWO="192.168.0.120" -t playground:1.0 .
方案2:运行时动态注入环境变量(适合需要在K8s部署时动态修改变量的场景,符合你的预期需求)
通过占位符替换的方式,在容器启动时将K8s注入的环境变量写入静态文件:
- 在React项目
public目录下新增config.js文件,定义全局占位变量:
window.APP_ENV = { ENV1: '__REACT_APP_ENV_VARIABLE__', ENV2: '__REACT_APP_ENV_VARIABLE_TWO__' }
- 在React项目的
public/index.html的head标签中引入该文件:
<script src="%PUBLIC_URL%/config.js"></script>
- 修改业务代码,读取全局变量而不是
process.env:
// 原来的process.env.REACT_APP_ENV_VARIABLE 替换为 window.APP_ENV.ENV1 // 原来的process.env.REACT_APP_ENV_VARIABLE_TWO 替换为 window.APP_ENV.ENV2
- 新增容器启动脚本
entrypoint.sh放在项目根目录:
#!/bin/sh # 替换config.js中的占位符为当前容器的真实环境变量 sed -i "s/__REACT_APP_ENV_VARIABLE__/$REACT_APP_ENV_VARIABLE/g" /usr/share/nginx/html/config.js sed -i "s/__REACT_APP_ENV_VARIABLE_TWO__/$REACT_APP_ENV_VARIABLE_TWO/g" /usr/share/nginx/html/config.js # 启动Nginx exec nginx -g 'daemon off;'
- 修改Dockerfile,新增启动脚本相关配置:
# 在最后阶段新增以下配置 COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]
重新构建镜像部署到K8s即可,Pod中定义的环境变量会在容器启动时自动注入到页面中。
内容的提问来源于stack exchange,提问作者AbreQueVoy
相关产品推荐
相关产品推荐

