我正在尝试容器化一个前端web应用程序,我遇到了麻烦,弄清楚如何传递环境变量。该应用程序是一个Angular应用程序,所以它是100%客户端的。
在一个典型的后端服务中,传递环境变量很容易,因为所有的东西都在同一个主机上运行,所以环境变量可以很容易地被后端服务选择。然而,在前端应用程序中,这是不同的:应用程序在客户端的浏览器中运行。
我想通过环境变量配置我的应用程序,因为这使部署更加容易。所有配置都可以在docker-compose.yml
中完成,并且不需要维护多个映像,每个可能的环境都有一个映像。只有一个不可变的映像。这遵循了12因素应用程序哲学,可以在https://12factor.net/config上找到。
我正在构建我的应用程序映像如下:
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
中做这样的事情:
backend:
image: ...
frontend:
image: my-frontend-app
environment:
- REST_API_URL=http://backend:8080/api
所以我认为我应该修改这个app/config.ts
,用环境变量替换REST_API_URL
。(所以我不想在构建过程中做这个替换),我很困惑如何在这里进行。我相信我应该支持在nginx代理启动之前在运行时更改app/config.ts
。然而,事实上,这个文件是缩小和webpack-bundled,使这更加diffucult。
有什么办法解决这个问题吗?
6条答案
按热度按时间ruyhziif1#
我解决这个问题的方法如下:
1.在environment.prod.ts中使用唯一且可识别的String设置值:
2.创建一个entryPoint.sh,每当您对容器执行Docker运行时,都会执行此entryPoint。
如您所见,此入口点获取'REST_API_URL_REPLACE'参数,并将其替换(在本例中)到main*bundle.js文件中,以获取var的值。
3.在entrypoint.shdockerfile中的CMD之前添加www.example.com(需要执行权限):
4.使用env启动镜像或使用docker-compose(斜杠必须转义):
可能存在一个更好的解决方案,不需要在缩小的文件中使用常规表达式,但这工作得很好。
tvokkenx2#
将您的环境变量放入
index.html
!!相信我,我知道你从哪里来的!在我的Angular应用程序的构建阶段烘焙特定于环境的变量违背了我所学到的关于可移植性和关注点分离的一切。
但是等等!仔细看看常见的Angular
index.html
:这是全部配置!!!
它就像你用来维护Docker应用的docker-compose.yml一样:
runtime
就像基本映像,您很少更改。*polyfills
是您需要的那些东西,它们没有包含在您需要的基础映像中。main
是您的实际应用程序,几乎每次发布都会发生变化。您可以在前端应用中执行与Docker应用相同的操作!
1.构建、版本化和发布不可变资产(js bundles / Docker镜像)
1.将部署清单发布到staging(index. html/ docker-compose.yml)
1.分期试验
1.将部署清单发布到生产环境..引用您刚刚测试的相同资产!立即!原子化!
怎么会
只需将发臭的
/src/environments/environment.prod.ts
指向window
对象。并使用环境变量**WHERE THEY BELONG!**将脚本添加到index.html中:
我对这种方法非常感兴趣,我创建了一个专门的网站:https://immutablewebapps.org.我想你会发现还有很多其他的好处!
rekjcdws3#
我在处理静态HTML文件时遇到了类似的问题,下面是我想要解决的问题:
我尝试了其他答案,但似乎它们不符合上面的要求。
Dockerfile
replaceEnvVars.sh
index.tmpl.html
docker-compose.yml
7kjnsjlb4#
我也在努力解决同样的问题,但还需要将配置值从docker-compose级别传递到Angular,我觉得这并不简单。
基本上,我采取了类似的方法,并提出了以下解决方案:
1.我使用compose ARGS将所需的值从
docker-compose.yml
传递到Dockerfile
。因此在docker-compose.yml
中我有:magicsword.core.web: build: args: - AUTH_SERVER_URL=http://${EXTERNAL_DNS_NAME_OR_IP}:55888/ - GAME_SERVER_URL=http://${EXTERNAL_DNS_NAME_OR_IP}:55889/ - GUI_SERVER_URL=http://${EXTERNAL_DNS_NAME_OR_IP}:55890/ # =self
1.现在必须在
Dockerfile
中将这些标记为变量:ARG AUTH_SERVER_URL ARG GAME_SERVER_URL ARG GUI_SERVER_URL
1.由于在构建过程中这些变量变成了正常的环境变量,最后一步是在目标文件中进行实际的替换,例如使用一些神奇的一行程序。我做了如下(只是一个宠物项目,所以不需要是最佳的):
RUN apt-get update && apt-get install -y gettext RUN envsubst < ./src/environments/environment.ts > ./src/environments/environment.ts.tmp && mv ./src/environments/environment.ts.tmp ./src/environments/environment.ts
替换前的
environment.ts
,供参考:export const environment = { production: true, GAME_SERVER_URL: "$GAME_SERVER_URL", GUI_SERVER_URL: "$GUI_SERVER_URL", AUTH_SERVER_URL: "$AUTH_SERVER_URL" };
瞧。希望这对某人有帮助:)
qvsjd97n5#
我的解决方案:在运行时使用docker卷来挂载特定的js配置文件作为env.js。
我有一个docker compose文件给dev和prod。
我有dev.env.js和prod.env.js。
我的html文件引用env.js。
在docker-compose.yml中,I卷将env文件挂载为env.js。
例如,我的开发人员组成:
我的刺组成:
dy1byipe6#
我只是在使用Docker和DotEnv webpack插件时遇到了这个问题。我想在多个环境中使用相同的镜像,所以我不得不延迟webpacking过程,直到镜像使用环境特定的ENV运行。
我通过创建start_app. sh并在入口点中运行它来做到这一点:
start_app.sh:
dockerfile结束:
docker命令: