让 Vue 项目的 Docker 镜像支持环境变量
背景
创业项目是前后端分离的,前端用 Vue,后端用 Laravel,分别打包成镜像,单独部署。因为学校用我们的服务时,都是不同的访问入口,即通过不同的域名进入系统,而不是在进入系统前要手动选择学校。
为了不在每个接口上都加上「学校」这个参数,我想到一个比较「优雅」的解决方案:每个学校的前端单独部署,通过设置 Docker 环境变量加上「学校」参数,在前端代码统一封装的 API 请求方法中,在 Header 增加该参数。
难点
为了尽可能地轻量化前端镜像,前端镜像是把 Vue 项目编译得到的产物拷贝到 nginx:alpine 镜像中,所以没有办法很优雅地让 Vue 项目读取容器运行的环境变量。
而且编译后的 JS 文件是直接在客户端运行,所以也就和容器环境变量没了关系。
解决方案
解决方案分为三步:
- 前端项目添加一个
env.js
文件,用于存储一些必要的环境变量,比如后端 API 地址还有本次要解决的「学校」参数问题 - 修改前端项目的
index.html
,加上<script src="<%= BASE_URL %>env.js"></script>
,引入环境变量 - 修改 Dockerfile 文件,添加
entrypoint.sh
,在容器运行时用sed
命令替换env.js
中的环境变量值
第三步有点抽象,给个代码会比较直观。
1 |
|
1 | # Dockerfile 示例 |
运行时,主动设置 XXXX_TOKEN
环境变量即可。
参考资料
- How to implement runtime environment variables with create-react-app, Docker, and Nginx
- Dockerize and configure a JavaScript single-page application