かなり単純なnode.jsアプリがありますが、AWS Elastic Beanstalkのデプロイメカニズムにより、単一のファイルコミットの後でも(git aws.Push
を介して)新しいバージョンをロールアウトするには約5分かかります。
つまりコミット自体(およびアップロード)は高速(Pushに1ファイルのみ)ですが、Elastic Beanstalkはパッケージ全体をS3から取得し、解凍してnpm install
を実行します。これにより、node-gypがいくつかのモジュールをコンパイルします。インストール/構築が完了すると、Elastic Beanstalkは/var/app/current
を消去し、新しいアプリバージョンに置き換えます。
言うまでもなく、node_modulesを継続的に再構築する必要はありません。古いMacbook Airでは30秒かかり、ec2.microインスタンスでは5分以上かかりますが、再構築は面白くありません。
ここには2つのアプローチがあります。
/opt/containerfiles/ebnode.py
を微調整し、node_modulesの場所を操作して、デプロイメント時の削除と再構築を回避します。npm install
を実行します(Elastic BeanstalkはOpsWorksのようになります。)どちらのオプションにも猶予がなく、AmazonがElastic Beanstalkフックとアーキテクチャを更新するときに問題が発生しやすくなります。
たぶん、誰かがアプリディレクトリにすでに存在するnode_modulesの継続的な再構築を避ける方法をより良いアイデアを持っていますか?ありがとうございました。
ありがとう、キリル、本当に助かりました!
npm install
の簡単な解決策を見ているだけの人のために設定ファイルを共有しています。このファイルは、プロジェクトの.ebextensions
フォルダーに配置する必要があります。ノードインストールの最新バージョンが含まれておらず、すぐに使用できるため、より軽量です。
また、インストールされているノードのバージョンを動的にチェックするため、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注:npm -gバージョンアップグレードを実行するスクリプトを更新し(1回のみ、初期インスタンスのロールアウトまたは再構築時)、EB構成変更中のNPM操作を回避します(アプリディレクトリが存在しない場合、エラーを回避し、構成の更新を高速化します)。
さて、Elastic Beanstalkは最近のnode.jsビルド(おそらくサポートされているv.0.10.10を含む)で危険な動作をするので、先に進んでTweak EBで次のことを行うことにしました。
基本的に、env.configを使用してdeploy&configフックをカスタマイズされたフックに置き換えます(以下を参照)。また、デフォルトのEBコンテナセットアップでは、いくつかの環境変数が欠落しています($HOME
例)およびnode-gyp
再構築中に失敗することがあります(これを解決するためにlibxmljsを2時間グーグルして再インストールしました)。
以下は、ビルドに含まれるファイルです。 env.configを介してインラインコードとして挿入するか、source: URL
(この例のように)
env.vars
(望ましいノードのバージョンとArchはここと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バージョンを取得してungzipし、グローバルシンボリックリンクを作成し、グローバル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を作成し、app 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
(ここにもノードのバージョンに注意してください。安全のために、AWSコンソールのenv configにも目的のノードのバージョンを入れてください。これらの設定のどちらが優先されるかはわかりません。)
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では、インスタンスの展開に10〜15分ではなく20〜30秒かかります。 1日に10回展開する場合、この調整により1年で3週間節約できます。私の失われた週末をAWS EBスタッフに感謝し、特別な感謝を捧げます:)
次のファイルを切り捨てることにより、npm install
コマンドのデフォルトのEB動作を上書きするnpmパッケージがあります。
https://www.npmjs.com/package/eb-disable-npm
このパッケージは維持されており、おそらくEBの動作が変更されたときに更新されるため、スクリプトをSOからコピーするよりも優れている可能性があります。
これに対する簡単な解決策を見つけました。 Amazonが使用しているビルドスクリプトを調べたところ、package.jsonが存在する場合にのみnpm install
が実行されます。したがって、最初のデプロイ後に_package.json
に変更すると、npm install
は実行されなくなります!これは最善の解決策ではありませんが、必要な場合は簡単に解決できます!