Подтвердить что ты не робот

Избежать перестройки node_modules в эластичном бобовом стебле

У нас довольно простое приложение node.js, но из-за механизма развертывания AWS Elastic Beanstalk требуется около 5 минут для развертывания новой версии (через git aws.push) даже после фиксации одного файла.

т.е. сама фиксация (и загрузка) выполняется быстро (только один файл для push), но затем Elastic Beanstalk извлекает весь пакет из S3, разархивирует его и запускает npm install, что заставляет node -gyp компилировать некоторые модули. После установки/завершения строительства, эластичные бобовые салфетки /var/app/current и заменяют его новой версией приложения.

Излишне говорить, что константа node_modules не нужна, а перестройка, которая занимает 30 секунд на моем старом Macbook Air, занимает > 5 минут на экземпляре ec2.micro, а не в весе.

Здесь я вижу два подхода:

  • tweak /opt/containerfiles/ebnode.py и играйте с node_modules, чтобы избежать его удаления и восстановления после развертывания.
  • настройте репозиторий git на Эластическом экземпляре ECC Beanstalk и в основном заново запишите процедуру развертывания самостоятельно, поэтому /var/app/current получает нажатие и запускает npm install только при необходимости (что делает эластичный beanstalk похожим на OpsWorks..)

Оба варианта не имеют изящества и склонны к проблемам, когда Amazon обновляет свои крючки и архитектуру из эластичного beanstalk.

Может кто-нибудь лучше подумает, как избежать постоянной перестройки node_modules, которые уже присутствуют в каталоге приложения? Спасибо.

4b9b3361

Ответ 1

Спасибо Кирилл, это было действительно полезно!

Я просто делюсь своим конфигурационным файлом для людей, которые просто смотрят простое решение для npm install. Этот файл необходимо поместить в папку .ebextensions проекта, он легче, поскольку он не включает последнюю версию установки node и готов к использованию.

Он также динамически проверяет версию node, поэтому нет необходимости включать ее в файл env.vars.

.ebextensions/00_deploy_npm.config

files:
  "/opt/elasticbeanstalk/env.vars" :
    mode: "000775"
    owner: root
    group: users
    content: |
      export NPM_CONFIG_LOGLEVEL=error
      export NODE_PATH=`ls -td /opt/elasticbeanstalk/node-install/node-* | head -1`/bin
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/50npm.sh" :
    mode: "000775"
    owner: root
    group: users
    content: |
      #!/bin/bash
      . /opt/elasticbeanstalk/env.vars
      function error_exit
      {
        eventHelper.py --msg "$1" --severity ERROR
        exit $2
      }

      #install not-installed yet app node_modules
      if [ ! -d "/var/node_modules" ]; then
        mkdir /var/node_modules ;
      fi
      if [ -d /tmp/deployment/application ]; then
        ln -s /var/node_modules /tmp/deployment/application/
      fi

      OUT=$([ -d "/tmp/deployment/application" ] && cd /tmp/deployment/application && $NODE_PATH/npm install 2>&1) || error_exit "Failed to run npm install.  $OUT" $?
      echo $OUT
  "/opt/elasticbeanstalk/hooks/configdeploy/pre/50npm.sh" :
    mode: "000666"
    owner: root
    group: users
    content: |
       #no need to run npm install during configdeploy

Ответ 2

25/01/13 ПРИМЕЧАНИЕ: обновленные сценарии для запуска обновления версии npm -g (только один раз, при развертывании или восстановлении исходного экземпляра) и во избежание действий NPM во время изменения конфигурации EB (когда приложение отсутствует, чтобы избежать ошибка и ускорить обновление конфигурации).

Хорошо, Elastic Beanstalk ведет себя изворотливым с недавними строками node.js(включая предположительно поддерживаемую v.0.10.10), поэтому я решил пойти и подстроить EB, чтобы сделать следующее:

  • для установки ЛЮБОЙ версии node.js в соответствии с вашим env.config(в том числе самые последние, которые еще не поддерживаются AWS EB)
  • чтобы избежать восстановления существующих модулей node, включая in-app node_modules dir
  • установить node.js глобально (и любой желаемый модуль).

В основном, я использую env.config для замены перехватчиков развертывания & config с настраиваемыми (см. ниже). Кроме того, в настройке EB-контейнера по умолчанию некоторые переменные env отсутствуют (например, $HOME), а node-gyp иногда терпит неудачу во время восстановления из-за этого (мне понадобилось 2 часа поиска и переустановки libxmljs, чтобы решить эту проблему).

Ниже приведены файлы, которые будут включены вместе с вашей сборкой. Вы можете вводить их через env.config как встроенный код или через source: URL (как в этом примере)

env.vars (желаемая версия node и арка включены здесь и в env.config, см. ниже)

export HOME=/root
export NPM_CONFIG_LOGLEVEL=error
export NODE_VER=0.10.24
export ARCH=x86
export PATH="$PATH:/opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/:/root/.npm"

40install_node.sh (выборка и разворачивание желаемой версии node.js, создание глобальных символических ссылок, обновление глобальной версии npm)

#!/bin/bash
#source env variables including node version
. /opt/elasticbeanstalk/env.vars

function error_exit
{
  eventHelper.py --msg "$1" --severity ERROR
  exit $2
}

#UNCOMMENT to update npm, otherwise will be updated on instance init or rebuild
#rm -f /opt/elasticbeanstalk/node-install/npm_updated

#download and extract desired node.js version
OUT=$( [ ! -d "/opt/elasticbeanstalk/node-install" ] && mkdir /opt/elasticbeanstalk/node-install ; cd /opt/elasticbeanstalk/node-install/ && wget -nc http://nodejs.org/dist/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && tar --skip-old-files -xzpf node-v$NODE_VER-linux-$ARCH.tar.gz) || error_exit "Failed to UPDATE node version. $OUT" $?.
echo $OUT

#make sure node binaries can be found globally
if [ ! -L /usr/bin/node ]; then
  ln -s /opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/node /usr/bin/node
fi

if [ ! -L /usr/bin/npm ]; then
ln -s /opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/npm /usr/bin/npm
fi

if [ ! -f "/opt/elasticbeanstalk/node-install/npm_updated" ]; then
/opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/ && /opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/npm update npm -g
touch /opt/elasticbeanstalk/node-install/npm_updated
echo "YAY! Updated global NPM version to `npm -v`"
else
  echo "Skipping NPM -g version update. To update, please uncomment 40install_node.sh:12"
fi

50npm.sh (создает/var/ node_modules, символизирует его в приложении dir и запускает npm install. Вы можете установить любой модуль по всему миру здесь, они приземляются в /root/.npm )

#!/bin/bash
. /opt/elasticbeanstalk/env.vars
function error_exit
{
  eventHelper.py --msg "$1" --severity ERROR
  exit $2
}

#install not-installed yet app node_modules
if [ ! -d "/var/node_modules" ]; then
  mkdir /var/node_modules ;
fi
if [ -d /tmp/deployment/application ]; then
  ln -s /var/node_modules /tmp/deployment/application/
fi

OUT=$([ -d "/tmp/deployment/application" ] && cd /tmp/deployment/application && /opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/npm install 2>&1) || error_exit "Failed to run npm install.  $OUT" $?
echo $OUT

env.config (также обратите внимание на версию node) и, чтобы быть в безопасности, поместите желаемую версию node в конфигурацию env в консоли AWS. Я не уверен, какой из этих настройки будут иметь приоритет.)

packages:
  yum:
    git: []
    gcc: []
    make: []
    openssl-devel: []

option_settings:
  - option_name: NODE_ENV
    value: production
  - option_name: RDS_HOSTNAME
    value: fill_me_in
  - option_name: RDS_PASSWORD
    value: fill_me_in
  - option_name: RDS_USERNAME
    value: fill_me_in
  - namespace: aws:elasticbeanstalk:container:nodejs
    option_name: NodeVersion
    value: 0.10.24

files:
  "/opt/elasticbeanstalk/env.vars" :
    mode: "000775"
    owner: root
    group: users
    source: https://dl.dropbox.com/....
  "/opt/elasticbeanstalk/hooks/configdeploy/pre/40install_node.sh" :
    mode: "000775"
    owner: root
    group: users
    source: https://raw.github.com/....
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/50npm.sh" :
    mode: "000775"
    owner: root
    group: users
    source: https://raw.github.com/....
  "/opt/elasticbeanstalk/hooks/configdeploy/pre/50npm.sh" :
    mode: "000666"
    owner: root
    group: users
    content: |
       #no need to run npm install during configdeploy
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/40install_node.sh" :
    mode: "000775"
    owner: root
    group: users
    source: https://raw.github.com/....

Там у вас есть: на t1.micro развертывание экземпляра теперь занимает 20-30 секунд вместо 10-15 минут! Если вы развертываете 10 раз в день, эта настройка позволит вам сэкономить 3 (три) недели в год. Надеюсь, что это поможет и особая благодарность сотрудникам AWS EB за мои упущенные выходные:)

Ответ 3

Там пакет npm, который перезаписывает поведение EB по умолчанию для команды npm install, обрезая следующие файлы:

  • /opt/elasticbeanstalk/hooks/appdeploy/pre/50npm.sh
  • /opt/elasticbeanstalk/hooks/configdeploy/pre/50npm.sh

https://www.npmjs.com/package/eb-disable-npm

Может быть лучше, чем просто копировать script из SO, поскольку этот пакет поддерживается и, вероятно, будет обновлен, когда поведение EB изменится.

Ответ 4

Я нашел быстрое решение. Я просмотрел скрипты сборки, которые использует Amazon, и они запускают только npm install, если присутствует package.json. Поэтому после вашего первоначального развертывания вы можете изменить его на _package.json, а npm install больше не будет работать! Это не лучшее решение, но это быстрое решение, если вам это нужно!

Ответ 5

У меня было 10 + минутные сборки, когда я разворачивал. Решение было намного проще, чем другие придумали... Просто проверьте node_modules на git! См. http://www.futurealoof.com/posts/nodemodules-in-git.html для обоснования