如何将环境变量传递给前端 Web 应用程序? [英] How to pass environment variables to a frontend web application?
问题描述
我正在尝试容器化前端 Web 应用程序,但在弄清楚如何传递环境变量时遇到了麻烦.该应用程序是一个 Angular 应用程序,因此它是 100% 的客户端.
I am trying to containerize a frontend web application and I am having troubles to figure out how to pass environment variables. The application is a Angular application, so it is 100% client-side.
在典型的后端服务中,传递环境变量很容易,因为一切都在同一主机上运行,因此后端服务可以轻松选择环境变量.但是,在前端应用程序中,这是不同的:应用程序运行在客户端的浏览器中.
In a typical backend service, passing environment variables is easy, as everything is running on the same host, so the environment variables can be easily picked by the backend service. However, in a frontend application, this is different: the application is running in the browser of the client.
我想通过环境变量配置我的应用程序,因为这使得部署更容易.所有配置都可以在 docker-compose.yml
中完成,无需维护多个镜像,每个可能的环境一个.只有一个不可变的图像.这遵循 12-factor 应用程序哲学,可以在 https://12factor.net/config 上找到.
I want to configure my application via environment variables, as this makes deployment much easier. All configuration can be done in docker-compose.yml
and there is no need to maintain several images, one for every possible environment. There is just one single immutable image. This follows the 12-factor application philosophy, as can be found on https://12factor.net/config.
我正在构建我的应用程序映像,如下所示:
I am building my application image as following:
FROM node:alpine as builder
COPY package.json ./
RUN npm i && mkdir /app && cp -R ./node_modules ./app
WORKDIR /app
COPY . .
RUN $(npm bin)/ng build
FROM nginx:alpine
COPY nginx/default.conf /etc/nginx/conf.d/
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /app/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
在 app/config.ts
中,我有:
export const config = {
REST_API_URL: 'http://default-url-to-my-backend-rest-api'
};
理想情况下,我想在我的 docker-compose.yml
中做这样的事情:
Ideally, I want to do something like this in my docker-compose.yml
:
backend:
image: ...
frontend:
image: my-frontend-app
environment:
- REST_API_URL=http://backend:8080/api
所以我相信我应该修改这个 app/config.ts
以用环境变量替换 REST_API_URL
.因为我更喜欢不可变的 Docker 镜像(所以我不想在构建过程中进行这个替换),我很困惑如何在这里取得进展.我相信我应该支持在 nginx 代理启动之前在运行时更改 app/config.ts
.然而,这个文件被缩小和 webpack 捆绑的事实使得这更加困难.
So I believe I should alter this app/config.ts
to replace REST_API_URL
with the environment variable. As I prefer an immutable Docker image (so I do not want to do this replace during the build), I am quite puzzled how to progress here. I believe I should support to alter the app/config.ts
at runtime before the nginx proxy is started. However, the fact that this file is minified and webpack-bundled, makes this more diffucult.
有什么想法可以解决这个问题吗?
Any ideas how to tackle this?
推荐答案
我的解决方法如下:
1.在enviroment.prod.ts中设置一个唯一且可识别的字符串值:
1.Set the value in the enviroment.prod.ts with a unique and identificable String:
export const environment = {
production: true,
REST_API_URL: 'REST_API_URL_REPLACE',
};
2.创建一个entryPoint.sh,这个entryPoint会在你每次对容器进行docker run时执行.
2.Create a entryPoint.sh, this entryPoint will be executed every time that you done a docker run of the container.
#!/bin/bash
set -xe
: "${REST_API_URL_REPLACE?Need an api url}"
sed -i "s/REST_API_URL_REPLACE/$REST_API_URL_REPLACE/g" /usr/share/nginx/html/main*bundle.js
exec "$@"
如您所见,此入口点获取REST_API_URL_REPLACE"参数并将其替换(在本例中) main*bundle.js 文件中的 var 值.
As you can see, this entrypoint get the 'REST_API_URL_REPLACE' argument and replace it (in this case) in the main*bundle.js file for the value of the var.
3.在dockerfile中CMD前添加entrypoint.sh(需要执行权限):
3.Add the entrypoint.sh in the dockerfile before the CMD (it need execution permissions):
FROM node:alpine as builder
COPY package.json ./
RUN npm i && mkdir /app && cp -R ./node_modules ./app
WORKDIR /app
COPY . .
RUN $(npm bin)/ng build --prod
FROM nginx:alpine
COPY nginx/default.conf /etc/nginx/conf.d/
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /app/dist /usr/share/nginx/html
# Copy the EntryPoint
COPY ./entryPoint.sh /
RUN chmod +x entryPoint.sh
ENTRYPOINT ["/entryPoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
4.使用 env 或使用 docker-compose 启动镜像(斜线必须转义):
4.Lauch the image with the env or use docker-compose (the slash must be escaped):
docker run -e REST_API_URL_REPLACE='http://backend:8080/api'-p 80:80 image:tag
可能存在一个更好的解决方案,不需要在缩小的文件中使用正则表达式,但这工作正常.
Probably exists a better solution that not need to use a regular expresion in the minified file, but this works fine.
这篇关于如何将环境变量传递给前端 Web 应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!