Nous avons une application node.js assez simple, mais en raison du mécanisme de déploiement AWS Elastic Beanstalk, il faut environ 5 minutes pour déployer une nouvelle version (via git aws.Push
) même après une validation de fichier unique.
C'est à dire. la validation elle-même (et le téléchargement) est rapide (seulement 1 fichier à pousser), mais ensuite Elastic Beanstalk récupère le paquet entier de S3, le décompresse et exécute npm install
, ce qui oblige node-gyp à compiler certains modules. Une fois l'installation/la construction terminée, Elastic Beanstalk essuie /var/app/current
et le remplace par la nouvelle version de l'application.
Inutile de dire que la reconstruction constante de node_modules n'est pas nécessaire, et une reconstruction qui prend 30 secondes sur mon ancien Macbook Air, prend> 5 minutes sur une instance ec2.micro, pas amusant.
Je vois deux approches ici:
/opt/containerfiles/ebnode.py
et jouez avec l'emplacement de node_modules pour éviter sa suppression et sa reconstruction lors du déploiement.npm install
uniquement lorsque cela est nécessaire (ce qui fait qu'Elastic Beanstalk ressemble à OpsWorks ..)Les deux options manquent de grâce et sont sujettes à des problèmes lorsque Amazon met à jour leurs crochets et leur architecture Elastic Beanstalk.
Peut-être que quelqu'un a une meilleure idée de la façon d'éviter la reconstruction constante de node_modules qui sont déjà présents dans le répertoire de l'application? Merci.
Merci Kirill, c'était vraiment utile!
Je partage juste mon fichier de configuration pour les personnes qui recherchent simplement la solution simple au npm install
. Ce fichier doit être placé dans le .ebextensions
dossier du projet, il est plus léger car il ne comprend pas la dernière version de l'installation du noeud, et prêt à l'emploi.
Il vérifie également dynamiquement la version du nœud installée, donc pas besoin de l'inclure dans le fichier 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
25/01/13 REMARQUE: scripts mis à jour pour exécuter la mise à niveau de la version npm -g (une seule fois, lors du déploiement ou de la reconstruction de l'instance initiale) et pour éviter les opérations NPM lors du changement de configuration EB (lorsque le répertoire d'application n'est pas présent, pour éviter les erreurs et accélérer les mises à jour de la configuration).
D'accord, Elastic Beanstalk se comporte de manière douteuse avec les versions récentes de node.js (y compris vraisemblablement prise en charge v.0.10.10), j'ai donc décidé d'aller de l'avant et Tweak EB pour faire ce qui suit:
Fondamentalement, j'utilise env.config pour remplacer les crochets de déploiement et de configuration par des crochets personnalisés (voir ci-dessous). De plus, dans une configuration de conteneur EB par défaut, certaines variables env sont manquantes ($HOME
par exemple) et node-gyp
échoue parfois pendant la reconstruction à cause de cela (il m'a fallu 2 heures pour googler et réinstaller libxmljs pour résoudre ce problème).
Vous trouverez ci-dessous les fichiers à inclure avec votre build. Vous pouvez les injecter via env.config sous forme de code en ligne ou via source: URL
(comme dans cet exemple)
env.vars
(la version du nœud et Arch souhaités sont inclus ici et dans env.config, voir ci-dessous)
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
(récupérer et décompresser la version node.js souhaitée, créer des liens symboliques globaux, mettre à jour la version globale de 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
(crée/var/node_modules, le relie symboliquement au répertoire de l'application et exécute npm install. Vous pouvez installer n'importe quel module globalement à partir d'ici, ils atterriront dans /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
(notez la version du nœud ici aussi, et pour être sûr, mettez également la version du nœud souhaitée dans la configuration env dans la console AWS. Je ne sais pas lequel de ces paramètres aura la priorité.)
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/....
Et voilà: le déploiement d'une instance t1.micro prend désormais 20 à 30 secondes au lieu de 10 à 15 minutes! Si vous déployez 10 fois par jour, ce Tweak vous fera gagner 3 (trois) semaines par an. J'espère que cela aide et merci au personnel AWS EB pour mon week-end perdu :)
Il existe un package npm qui remplace le comportement EB par défaut pour npm install
commande en tronquant les fichiers suivants:
https://www.npmjs.com/package/eb-disable-npm
Cela pourrait être mieux que simplement copier le script depuis SO, car ce paquet est maintenu et sera probablement mis à jour lorsque le comportement d'EB changera.
J'ai trouvé une solution rapide à cela. J'ai parcouru les scripts de construction qu'Amazon utilise et ils n'exécutent que npm install
si package.json est présent. Ainsi, après votre déploiement initial, vous pouvez le remplacer par _package.json
et npm install
ne fonctionnera plus! Ce n'est pas la meilleure solution mais c'est une solution rapide si vous en avez besoin!