Как улучшить время сборки проекта Angular 5 с помощью Docker?

Я пытаюсь улучшить время сборки моей автоматизации. Прямо сейчас требуется всего 14 минут, чтобы построить интерфейс.

enter image description here


Это то, что я получил до сих пор

web.dockerfile

### STAGE 1: Build ###
FROM node:9.3.0-alpine as builder

COPY package.json ./

RUN npm set progress=false && npm config set depth 0 && npm cache clean --force

## Storing node modules on a separate layer will prevent unnecessary npm installs at each build
RUN npm i
RUN mkdir /web
RUN cp -R ./node_modules ./web

WORKDIR /web

COPY . .

RUN $(npm bin)/ng build --prod --build-optimizer

### STAGE 2: Setup ###

FROM nginx:1.13.8-alpine

COPY nginx.conf /etc/nginx/nginx.conf
COPY site.conf /etc/nginx/conf.d/default.conf
RUN rm -rf /usr/share/nginx/html/*

COPY --from=builder /web/dist /usr/share/nginx/html/

RUN touch /var/run/nginx.pid && \
  chown -R nginx:nginx /var/run/nginx.pid && \
  chown -R nginx:nginx /var/cache/nginx && \
  chown -R nginx:nginx /usr/share/nginx/html

USER nginx

RUN $(npm bin)/ng build --prod --build-optimizer

Эта строка выше занимает почти 99% времени сборки.


.angular-cli.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "project": {
    "name": "web"
  },
  "apps": [{
    "root": "src",
    "outDir": "dist",
    "assets": [
      "assets",
      "favicon.ico"
    ],
    "index": "index.html",
    "main": "main.ts",
    "polyfills": "polyfills.ts",
    "test": "test.ts",
    "tsconfig": "tsconfig.app.json",
    "testTsconfig": "tsconfig.spec.json",
    "prefix": "app",
    "styles": [
      "styles.css",
      "../node_modules/bootstrap/dist/css/bootstrap.min.css",
      "../node_modules/ngx-toastr/toastr.css",
      "../src/assets/css/style.css",
      "../src/assets/css/colors/blue.css"

    ],
    "scripts": [
      "../node_modules/jquery/dist/jquery.min.js",
      "../node_modules/popper.js/dist/umd/popper.min.js",
      "../node_modules/bootstrap/dist/js/bootstrap.min.js",
      "../node_modules/jquery-slimscroll/jquery.slimscroll.min.js",
      "../node_modules/pace-js/pace.min.js"
    ],
    "environmentSource": "environments/environment.ts",
    "environments": {
      "dev": "environments/environment.ts",
      "prod": "environments/environment.prod.ts"
    }
  }],
  "e2e": {
    "protractor": {
      "config": "./protractor.conf.js"
    }
  },
  "lint": [{
      "project": "src/tsconfig.app.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "src/tsconfig.spec.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "e2e/tsconfig.e2e.json",
      "exclude": "**/node_modules/**"
    }
  ],
  "test": {
    "karma": {
      "config": "./karma.conf.js"
    }
  },
  "defaults": {
    "styleExt": "css",
    "component": {}
  }
}

Environment

DockerCloud подключиться к моему AWS

AWS: EC2 micro


Результат

Этот докер файл работает отлично, и он создает успех.

Но это занимает около 14 минут, чтобы построить. Можно ли улучшить это? Это из-за моего экземпляра слишком мало процессора?

Ответ 1

[TL; DR]

  • Используйте тома для хранения node_modules и .npm
  • Параллелизировать части вашего процесса (например, тесты)
  • Будьте осторожны при использовании относительных путей
  • Не копируйте весь проект с помощью COPY . .. Относительные проблемы пути и возможные утечки информации.
  • Создайте отдельное изображение, содержащее только основные зависимости для построения и тестирования (например, npm, java, chrome-driver, libgconf2).
  • Настроить конвейеры для использования этого образа
  • Пусть CI клонирует репо и копирует ваш проект в контейнер для сборки и тестирования.
  • Архивированные файлы (например, dist) и тег, основанные на частоте отказов
  • Создайте новое изображение с достаточным количеством вещей для запуска ваших встроенных файлов.

[ДЛИННАЯ ВЕРСИЯ]

Существует хорошая вероятность того, что ваши зависимости npm будут повторно загружены и/или ваши изображения докеров будут перестроены для каждой вашей сборки.

Вместо копирования файлов в образ докеры лучше было бы монтировать тома для модулей и кеша, чтобы дополнительные зависимости, включенные позже, не нужно было загружать снова. Типичными каталогами, которые следует учитывать при создании томов, являются npm_modules (один для глобального и один для локального) и .npm(cache).

Ваш package.json копируется в root /, а тот же package.json копируется в /web с COPY . ..

Начальный запуск npm i устанавливается в /, и вы снова запускаете его для /web. Вы загружаете зависимости дважды, но могут ли модули в / использоваться для чего-либо? Независимо от того, вы, как представляется, используете тот же пакет .json как в npm i, так и в ng build, поэтому одно и то же выполняется дважды, ([EDIT] - Казалось бы, ng build не redownload), но node_modules недоступен в /, поэтому команда npm i создает другую и повторно загружает все пакеты.

Вы создаете каталог web в корневом каталоге /, но есть другие команды, инструктирующие относительные пути ./web. Вы уверены, что все работает в нужных местах? Нет никакой гарантии, что программы будут искать в каталогах, которые вы хотите, если вы используете относительные пути. Хотя может показаться, что он работает для этого изображения, такая же практика не будет согласована между другими изображениями, которые могут иметь разные начальные рабочие каталоги.

[может быть или не быть релевантной информацией]

Хотя я не использую Bitbucket для автоматизации сборки, я столкнулся с подобной проблемой при работе с конвейерами Jenkins. Дженкинс разместил проект в другом каталоге, так что каждый раз, когда он запускается, все зависимости будут загружены снова. Первоначально я думал, что проект будет находиться в /home/agent/project, но он был фактически размещен в другом месте. Я нашел каталог, в который был скопирован проект, с помощью команды pwd и npm cache verify на этапе сборки, затем смонтировал тома в нужные места. Вы можете просмотреть результат в журналах, сгенерированных в сборках.

Вы можете просмотреть результат, расширив раздел на странице конвейеров.

введите описание изображения здесь

Если изображение перестраивается при каждом запуске, создайте изображение отдельно, а затем нажмите изображение в реестр. Настройте файл конвейера для использования вашего изображения. Вам следует попытаться использовать уже имеющиеся базовые изображения, если это возможно, если нет других зависимостей, которые вам нужны, которые недоступны в базовом изображении (такие вещи, как alpine apk packages, а не npm. Зависимости npm могут храниться в томах). Если вы собираетесь использовать общий реестр, не храните файлы, которые могут содержать конфиденциальные данные. Настройте конвейер так, чтобы все было установлено с томами и/или использовало секреты.

Базовая реструктуризация на этапах тестирования и сборки.

       Image on Docker Hub
              |
              |
           ---|-------------------------------------|
           |                       |                |
           V                       V                |
Commit -- build (no test) ---> e2e tests (no build)-]--+--> archive build --> (deploy/merge/etc)
                         |           _______________|  ^
                         |           v                 |
                         |-> unit tests (no build)---->|

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