在Docker容器环境中configurationAngular 2 Webpack App

我们希望在不同的环境中使用Docker镜像来部署我们的Angular 2应用程序(staging / test,production,…)

在本地开发时,我们通过http:// localhost:8080连接到后端REST API,但是当我们在不同的环境中部署时,我们希望使用相同的Docker镜像并连接到不同的REST API端点

在运行时将此configuration注入Docker容器的首选方法是什么?

有没有办法通过环境variables做到这一点?

我们可以通过包含类似的纯文本文件来做到这一点

{ "BASE_URL": "https://api.test.example.com" } 

在这篇文章和twitter上进行了一些讨论之后,看起来好像没有简单的方法来通过Webpack实现我想要的功能。 这些文件仅在运行时作为静态文件提供,不可能在构建时排除文件,并在运行时将其包含在内。

所以我决定去解决方案/解决方法,我想到:更改启动码头容器时的静态文件。

我通过做创建我的码头形象

 npm run build:prod docker build -t angularapp . 

我正在使用官方的nginx泊坞窗图像作为我的基本形象和Dockerfile的样子

 FROM nginx:1.11.1 COPY dist /usr/share/nginx/html COPY run.sh /run.sh CMD ["bash", "/run.sh"] 

run.sh用于通过sed修改配置文件,然后启动nginx:

 #!/bin/sh /bin/sed -i "s|http://localhost:8080|${BASE_URL}|" /usr/share/nginx/html/api.config.chunk.js nginx -g 'daemon off;' 

这使我可以通过我docker-compose.yml文件中的环境变量来配置BASE_URL (简化):

 version: '2' services: api: image: restapi frontend: image: angularapp environment: BASE_URL: https://api.test.example.com 

通过这个解决方案/解决方法,我可以通过在启动Docker容器时配置通过环境变量使用的REST API端点来部署由我的jenkins作业创建的docker镜像,以便在我的所有环境(开发,临时,生产)中部署特定的版本。

这里的最终解决方案完全依赖于你的CI / CD工具链,但是这个解决方案可以模制成任何东西。

第一步:添加一些像https://github.com/motdotla/dotenv到你的dependencies这将处理你的配置值。 还有其他的选择,根据你的需要,滚动你自己很容易。

根据文档,在您的应用程序中尽早加载配置(全球app.module.ts是我个人的选择,因为我们希望这是全球可用的)。

简单地说 – 基于process.env.NODE_ENV你将会为每个堆栈加载不同的配置,并且使DX变得简单,我总是给配置值一个默认值,这样我的开发人员就不用担心这个文件了。

对于TESTING, STAGING, PRODUCTION – 例如,您要在环境变量中为您正在使用的任何CI提供程序设置BASE_URL_STAGINGBASE_URL_PRODUCTION

作为CI运行的一部分,基于git分支,将你的配置值写入一个.env文件,然后在你的Dockerfile添加一个COPY文件。 docker-compose.ymldocker-compose.yml您在docker-compose.yml构建期间刚写入的环境文件。

在验证之后,当您推送新的Docker镜像时,.env是部署包中的一部分,用于定位您所需的任何环境特定端点。

我会采取稍微不同的,但以一种类似于你的sed -sllscript的方式。

我喜欢你提到的“纯文本配置文件”的想法,这个如何:

从一个已知的位置服务配置文件,例如./config ? 由于你的JS已经从当前的网站加载,至少在那里你应该能够依靠相对路径。

步骤1:docker容器中启动的shell脚本将配置参数从环境变量写入明文文件,并将其放在与打包的角码相同的文件夹中。

第2步:在加载应用程序的主HTML文件中,有一些像这样的init代码:

 $(function() { $.get('./config') .then(function(res) { window.appConfig = res.data; // your bootstrapping call angular.bootstrap(....); }); }); 

第3步:在角度应用程序中使用全局变量,例如,如果使用的是OpaqueToken:

 import { OpaqueToken } from '@angular/core'; const CONFIG_TOKEN = new OpaqueToken('config'); export const THIRDPARTYLIBPROVIDERS = [ { provide: CONFIG_TOKEN, useValue: window.appConfig } ]; 

是的,这仍然有点不好意思,在你的dev-env中,用于服务ng-app的节点代理也必须公开这样一个配置端点。 这也需要额外的请求,但是通过扩展init-code来缓存localStorage中的数据(假设这些数据不会随着时间的推移而变化),这很容易避免。

但是总的来说,我认为这样做比维护一些你不知道它们是如何布置的文件要容易一些。

让我知道你的想法!