公司需要同一套代码部署两个系统,实现一个镜像同时发布两个项目,大佬们拍板决定在k8s配置env在运行时动态读取环境变量
以下为gdp调研并结合项目代码,整合而得的实现步骤,已经发版部署,目前没有发现问题,项目成功在运行时读取环境变量
dockerfile文件
FROM nginx:stable
# 复制 Vue 构建后的静态文件
COPY dist /usr/share/nginx/html
# 复制 Nginx 配置文件
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 使用 ENTRYPOINT 让容器启动时动态生成 config.js。需要放置在一个文件夹中,不能直接放到根目录/usr/share/nginx/html/config.js,会无法访问(奇怪的bug)
ENTRYPOINT ["/bin/sh", "-c", "echo \"window._env_ = { VUE_APP_BASE_API: '$VUE_APP_BASE_API' };\" > /usr/share/nginx/html/js/config.js && exec nginx -g 'daemon off;'"]
EXPOSE 80
nginx.conf
修改 nginx.conf,确保 config.js 不被缓存
如果不写:config.js 可能会被缓存,导致环境变量更新后,前端仍然使用旧的 API 地址
location /js/config.js {
root /usr/share/nginx/html;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate";
expires 0;
}
public/index.html
根目录引入config.js。不能直接用 /config.js 或者 ./config.js,因为运行后无法使用根目录访问 (奇怪的事情)
必须在挂载app前引入
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="expires" content="0">
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/>
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<script src="/js/config.js"></script>
utils/ request.js
window._env_?.VUE_APP_BASE_API 让 Vue 从 config.js 读取 API 地址,这个文件会在 K8s 运行时生成。(dockerfile文件设置
不要用 process.env.VUE_APP_BASE_API,因为 Vue process.env 只在 build 时生效,而不是 run 时!
const service = axios.create({
// baseURL: process.env.VUE_APP_BASE_API,
baseURL: window._env_?.VUE_APP_BASE_API || process.env.VUE_APP_BASE_API,
timeout: 180000,
});
k8s修改yaml,配置环境变量
apiVersion: apps/v1
kind: Deployment
metadata:
name: vue-app
spec:
replicas: 1
template:
spec:
containers:
- name: vue-app
image: my-vue-app:latest
env:
- name: VUE_APP_BASE_API
value: "http://www.baidu.com:82"
容器检查
进入容器检查k8s是否传入环境变量。例如我的环境变量设置的是:http://www.baidu.com:82
echo $VUE_APP_BASE_API
#正确传入显示
http://www.baidu.com:82
如果是空的,说明 Kubernetes 没有正确传入环境变量。
dockerfile文件设置动态生成的config.js文件目录为 /usr/share/nginx/html/js/config.js
检查运行的项目中是否存在 /usr/share/nginx/html/js文件
#进入/usr/share/nginx/html/js文件
cd /usr/share/nginx/html/js
#进入后列出指定目录下的文件和目录名称:ls
#显示js文件夹中有以下10个js文件
/usr/share/nginx/html/js# ls
chunk.0.1742461339950.js chunk.2.1742461339950.js chunk.4.1742461339950.js chunk.6.1742461339950.js config.js
chunk.1.1742461339950.js chunk.3.1742461339950.js chunk.5.1742461339950.js chunk.chunk-vendors.1742461339950.js jsapp.1742461339950.js
#查看config.js
cat /usr/share/nginx/html/js/config.js
window._env_ = { VUE_APP_BASE_API: 'http://www.baidu.com:82' };
成功后将项目中所有 process.env.VUE_APP_BASE_API 改为 window.env?.VUE_APP_BASE_AP