Angular. base-href через переменные окружения docker контейнера

Отличие baseHref от deployUrl

Постановка задачи

В продукте, разработкой которого сейчас занимаюсь, frontend может разворачивать на поддомене (dci.example.com) или на префиксе маршрута (example.com/dci). В соответствии с Twelve-Factor App конфигурация приложения должна хранится в переменных окружения.

Требуется с помощью переменных окружения задавать base-href, deploy-url, и режим box (true/false). box используется в файле Angular окружения.

export const environment: DCIEnvironment = {
  production: false,
  box: false,
};

Решение

В angular.json в production конфигурацию добавляется placeholders __BASE_HREF__ и __DEPLOY_URL__.

  "configurations": {
    "production": {
      "baseHref": "__BASE_HREF__",
      "deployUrl": "__DEPLOY_URL__",
      "fileReplacements": [
        {
          "replace": "src/environments/environment.ts",
          "with": "src/environments/environment.prod.ts"
        }
      ],

В environment.prod.ts добавляется __BOX__.

export const environment: DCIEnvironment = {
  production: true,
  box: '__BOX__',
};

После сборки приложения, index.html содержит следующий код:

<!doctype html>
<html lang="en">
<head>
  <base href="__BASE_HREF__">
  <meta charset="utf-8">
  <title>DCImanager</title>
  ...
  <link rel="stylesheet" href="__DEPLOY_URL__styles.6abf673a49ca32fc7a11.css">
</head>
<body>
  <ispdci-root></ispdci-root>
  <script src="__DEPLOY_URL__runtime-es2015.f80f277e876e950e3280.js" type="module"></script>
  ... 
</body>
</html>

__BOX__ и __DEPLOY_URL__ находятся в нескольких js чанках:

  • runtime-es5.<hash>.js
  • runtime-es2015.<hash>.js
  • main-es5.<hash>.js
  • main-es2015.<hash>.js

Во время запуска контейнара эти placeholders должны получить корректные значения.

Dockerfile

FROM nginx:1.19
COPY  dist/ispdci /usr/share/nginx/html
COPY  nginx/saas.default.conf /etc/nginx/conf.d/default.conf
COPY docker-entrypoint.sh /
RUN chmod +x docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

docker-entrypoint.sh

#!/usr/bin/env bash
set -Eeo pipefail
sed -i -e "s|__BASE_HREF__|"${BASE_HREF:-/}"|" \
       -e "s|__DEPLOY_URL__|"${DEPLOY_URL:-''}"|g" \
       -e "s|\"__BOX__\"|"${BOX:-false}"|g" /usr/share/nginx/html/*.*
exec "$@"

Значения при отсутствии переменных:

  • BASE_HREF - /
  • DEPLOY_URL - пустая строка ''
  • BOX - false

Указание /usr/share/nginx/html/*.* для sed запускает замену во всех файлах директории нерекурсивно (не включает вложенные директории).

Использование

  dci_front:
    image: registry.ispsystem.com/team/dci/front:1.74.0
    labels:
      SERVICE_BOXED: "true"
      SERVICE_CHECK_INTERVAL: 10s
      SERVICE_CHECK_TCP: "true"
      SERVICE_CHECK_TIMEOUT: 1s
      SERVICE_NAME: dci_front
      SERVICE_TAGS: static,frontend
      SERVICE_URI: '/dci'
    environment:
      BASE_HREF: '/dci'
      # DEPLOY_URL: '/dci/' необязательная переменная
      BOX: "true"
    networks:
      auth: null
    depends_on:
    - registrator
    restart: always

Похожие записи

Angular. Manually retry http request

На память. Некоторое время назад я решил достаточно необычную задачу, но в последствии на backend`е переделали логику и код был удалён из проекта.