【问题标题】:configure Angular 2 Webpack App in Docker container environment specific在特定的 Docker 容器环境中配置 Angular 2 Webpack App
【发布时间】:2017-03-15 18:20:56
【问题描述】:

我们希望使用 Docker 映像 在不同的环境(暂存/测试、生产...)中部署我们的 Angular 2 应用

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

在运行时注入配置Docker容器的首选方法是什么?

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

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

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

【问题讨论】:

  • 您使用的是 angular-cli 还是自定义构建?
  • 抱歉,我不熟悉 werbpack-starter repo 的工作原理。我们正在使用的 angular-cli 具有您描述的选项(环境)。
  • 据我所知,这些环境是在构建时使用而不是在运行时使用的,我们正在寻找一种在运行时配置应用程序的方法
  • 你是对的。但是使用您的 docker 解决方案,您不会在运行之前在 docker 中构建您的应用程序吗?

标签: angular nginx docker webpack


【解决方案1】:

这里的最终解决方案完全取决于您的 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

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

验证后,当您推送新的 docker 映像时,.env 是部署包的一部分,针对您需要的任何环境特定端点。

【讨论】:

  • 这不会导致我想要的:我想要一个特定版本的 docker 映像,我可以将其部署到具有不同配置的多个环境:(
  • 传递环境变量的机制并不重要。像 dotenv 和它相关的 webpack 插件之类的东西只是将外部环境变量连接到您的应用程序。您可以轻松地将 BASE_URL_STAGING 之类的内容传递到您的 docker run 命令 docker run -e 或您的 docker-compose 中,例如 .. environment: - BASE_URL=${BASE_URL_FROM_ENVIRONMENT} 这是一个两部分的问题。 dotenv 处理将外部变量导入您的应用程序,设置这些变量是特定于工具链的
  • 我明白,但重要的是我不想为不同的环境(登台、生产……)构建多个 docker 镜像。我只想运行一次 npm run build:prod 并将创建文件的打包到 docker 映像中
【解决方案2】:

在这篇文章和 Twitter 上进行了一些讨论之后,似乎没有简单的方法可以通过 Webpack 实现我想要的。这些文件在运行时仅作为静态文件提供,无法在构建时排除文件并在运行时包含它。

所以我决定采用我想到的解决方案/解决方法:在启动 docker 容器时更改静态文件。

我通过这样做来创建我的 docker 映像

npm run build:prod
docker build -t angularapp .

我使用官方的 nginx docker 镜像作为我的基础镜像,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 映像.

【讨论】:

  • 我尝试了您在此处生成的所有解决方案,但都失败了,请您与我分享您的代码。我也应该这样做。
【解决方案3】:

我会采取与您的sed-shellscript 稍有不同但方式相似的方法。

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

从已知位置提供配置文件,例如./config? 由于您的 JS 已经从当前站点加载,至少在那里您应该能够依赖相对路径。

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

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

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

第 3 步:在 Angular 应用中使用全局变量,例如如果您使用的是 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 提供服务的节点代理也必须公开这样的配置端点。 这也需要一个额外的请求,但是这可以通过扩展初始化代码来轻松避免,例如将数据缓存在 localStorage 中(假设这些数据不会随着时间的推移而真正改变)。

但总而言之,我认为这比 sed 更易于维护一些你并不真正知道它们是如何布局的文件。

让我知道你的想法!

【讨论】:

    猜你喜欢
    • 2017-07-04
    • 2017-10-22
    • 2018-06-02
    • 1970-01-01
    • 2017-08-21
    • 2017-05-30
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多