将环境变量传入Angular Docker容器

2exbekwf  于 2023-06-29  发布在  Docker
关注(0)|答案(2)|浏览(143)

我有一个设置使用本教程:https://codinglatte.com/posts/angular/using-os-environment-variables-in-angular-with-docker/将docker环境变量传递到docker容器中。
我正在使用一个有Angular 的自定义webpack。
然而,当我打开docker容器并打开应用程序时,似乎我的docker变量没有传递到angular容器中。
如何正确地将docker env变量传递到我的Angular App中?
下面是我的angular应用程序的Dockerfile:

FROM node:12 AS compile-image

WORKDIR /opt/ng

COPY package.json ./

RUN npm install

COPY . ./

RUN node_modules/.bin/ng build --prod

FROM nginx

VOLUME [ "/usr/share/nginx/html/data" ]

WORKDIR /

COPY --from=compile-image /opt/ng/dist/YomiApp /usr/share/nginx/html

还有我的docker-compose.yml,我用它来打开Angular容器和应用的后端服务器:

version: "3"

services:
  webapp:
    image: nlanson/myAngularImage:latest
    environment:
      TZ: Australia/Sydney
      DATABASE_URI: "http://localhost:6969"
    volumes:
      - "./data:/usr/share/nginx/html/data" #Data is mounted to the directory where the Angular App is running.
    ports:
      - "8080:80"
    container_name: webapp
  server:
    image: nlanson/backendImage:latest
    environment:
      TZ: Australia/Sydney
    volumes:
      - "./data:/data"
    ports:
      - "6969:6969"
    container_name: server

下面是我的custom-webpack.config.js文件,其中列出了我的环境变量:

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      $ENV: {
        DATABASE_URI: JSON.stringify(process.env.DATABASE_URI),
      }
    })
  ]
};

以及使用环境变量的服务:

import { environment } from '../../environments/environment'

@Injectable({
    providedIn:root
})
export class DatabaseService {
    URI = environment.DATABASE_URI
}

也许是因为我的Angular Image的构建是多阶段的??
谢谢

hi3rlvi2

hi3rlvi21#

webapp容器使用的环境变量需要在构建过程中传递给容器,而不是初始化。这些环境变量由RUN node_modules/.bin/ng build --prod使用。但是这些环境变量并不是在那一刻设置的,它们将在镜像构建完成后由docker-compose设置。您需要在Dockerfile中设置这些变量。

2jcobegt

2jcobegt2#

你的方法总是会失败,因为webpack脚本在构建容器的过程中只运行一次。所以你需要一些在每次容器启动时运行的代码来修改som代码。
我目前的做法是:
1.容器启动时:在Dockerfile中-作为入口点运行bash脚本:

# Docker code for building the image

# Transfer env variables to be able to read them in the javascript code
COPY docker-env-js-to-script.sh /
RUN ["chmod", "+x", "/docker-env-js-to-script.sh"]
ENTRYPOINT ["/docker-env-js-to-script.sh"]
CMD ["node", "server.js"]

1.阅读所有从APP_开始的env变量:

#!/bin/sh
set -euo pipefail

# Capture all environment variables starting with APP_ and make JSON string from them
ENV_JSON="$(jq --compact-output --null-input 'env | with_entries(select(.key | startswith("APP_")))')"

# Escape sed replacement's special characters: \, &, /.
# No need to escape newlines, because --compact-output already removed them.
# Inside of JSON strings newlines are already escaped.
ENV_JSON_ESCAPED="$(printf "%s" "${ENV_JSON}" | sed -e 's/[\&/]/\\&/g')"

sed -i "s/<noscript id=\"env-insertion-point\"><\/noscript>/<script>var env=${ENV_JSON_ESCAPED}<\/script>/g" /app/index.html

exec "$@"

1.通过将<noscript id="env-insertion-point"></noscript>(添加到index.html的主体中)替换为env变量作为json,将这些变量添加到index.html文件中。
1.在JavaScript中,在环境文件中将使用以下代码从默认值或环境中获取变量:

export const environment = {
  get apiAddress() {
    if (window.env && window.env.APP_API_BASE_URL) {
      return window.env.APP_API_BASE_URL;
    } else {
      return defaultEnvironment.apiBaseUrl;
    }
  }
};

通过这样做,我们可以在第一次启动容器时定义--env APP_API_BASE_URL=api.company.com
这种方法的主要缺点是浏览器可能会缓存index.html文件。这对我们来说不是问题。但这对你来说可能是个问题,所以请记住这一点。

相关问题