Customize AWS ElasticBeanstalk NodeJS Install (use yarn)
Solution 1
I've figured out a way, but it is a little hacky.
- Create a
.ebextensions/yarn.config
file. (The name does not have to be 'yarn'.) -
Put this content into the file:
files: # Runs right before `npm install` in '.../50npm.sh' "/opt/elasticbeanstalk/hooks/appdeploy/pre/49yarn.sh" : mode: "000775" owner: root group: users content: | #!/bin/bash app="$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)"; # install node curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -; # install yarn curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo; yum -y install yarn; # install node_modules with yarn cd "${app}"; yarn --production;
This ebextension creates a file which does 3 things:
- Installs node.
- Installs yarn.
- Installs node_modules with yarn.
In order to make Elastic Beanstalk run yarn install
before it runs npm install
, the file is created under /opt/elasticbeanstalk/hooks/appdeploy/pre
. This turns the file into a pre-deployment hook, which means that Elastic Beanstalk will run it during the first phase of deployment. By default, there is another file in this directory called 50npm.sh
, which runs npm install
. Since Elastic Beanstalk runs the files in this directory alphabetically, 49yarn.sh
(our file) will run before 50npm.sh
(the default file), resulting in yarn install
running before npm install
.
One potential problem is that the environment variables set in the Elastic Beanstalk UI (under Configuration
> Software Configuration
) are not available at this point of the deployment phase. This is a big problem if you have an npm auth token there which you use to install private npm modules.
Another potential problem is that this installs node manually, so the "Node version" you specify in the Elastic Beanstalk UI (under Configuration
> Software Configuration
) will have no effect on the version of node your application uses; you need to specify it in this ebextension. Elastic Beanstalk's 50npm.sh
both installs node and runs npm install
. Since we have to run yarn install
before that file runs, we also have to install node manually. Then, when Elastic Beanstalk goes to install node, it detects that node is already installed but does not verify that it is the correct version, so it skips the node installation.
For reference, the yarn installation instructions came from here: https://yarnpkg.com/docs/install#linux-tab
Solution 2
I did this following instructions on https://yarnpkg.com/lang/en/docs/install/
commands:
01_install_yarn:
command: "sudo wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo && curl --silent --location https://rpm.nodesource.com/setup_6.x | sudo bash - && sudo yum install yarn -y"
Solution 3
This way that i came up with lets you still control the node version via the Elastic Beanstalks Dashboard.
Thanks for this question! couldn't have come to this solution without it :D
"/opt/elasticbeanstalk/hooks/appdeploy/pre/50npm.sh":
mode: "000755"
owner: root
group: users
content: |
#!/usr/bin/env bash
#
# Prevent installing or rebuilding like Elastic Beanstalk tries to do by
# default.
#
# Note that this *overwrites* Elastic Beanstalk's default 50npm.sh script
# (https://gist.github.com/wearhere/de51bb799f5099cec0ed28b9d0eb3663).
"/opt/elasticbeanstalk/hooks/configdeploy/pre/50npm.sh":
mode: "000755"
owner: root
group: users
content: |
#!/usr/bin/env bash
#
# Prevent installing or rebuilding like Elastic Beanstalk tries to do by
# default.
#
# Note that this *overwrites* Elastic Beanstalk's default 50npm.sh script.
# But their default script actually doesn't work at all, since the app
# staging dir, where they try to run `npm install`, doesn't exist during
# config deploys, so ebnode.py just aborts:
# https://gist.github.com/wearhere/de51bb799f5099cec0ed28b9d0eb3663#file-ebnode-py-L140
"/opt/elasticbeanstalk/hooks/appdeploy/pre/49yarn.sh" :
mode: "000775"
owner: root
group: users
content: |
tmp="$(mktemp || bail)";
app="$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)";
version="$(/opt/elasticbeanstalk/bin/get-config optionsettings -n aws:elasticbeanstalk:container:nodejs -o NodeVersion)";
echo $version
major="$(cut -d'.' -f1 <<<${version})"
yum -y install python26 python26-libs
wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo;
wget "https://rpm.nodesource.com/pub_${major}.x/el/7/x86_64/nodejs-${version}-1nodesource.x86_64.rpm" -O "${tmp}";
rpm -i --nosignature --force "${tmp}";
rm -f "${tmp}";
yum -y install yarn;
cd "${app}";
yarn --production;
Solution 4
Had to revisit this as we couldn't figure out why we were stuck on node 8 even though we set it to node 12 in the EB UI. Seems that if you install a global node it overrides the version setting. Instead of installing a global node, this uses the Elastic Beanstalk node install and adds it to the path. You have to add the PATH in again at the start of your yarn install script but it seems to be the least invasive way to use yarn.
content: |
#!/usr/bin/env bash
set -euxo pipefail
EB_NODE_VERSION=$(/opt/elasticbeanstalk/bin/get-config optionsettings -n aws:elasticbeanstalk:container:nodejs -o NodeVersion)
echo "EB node version: $(EB_NODE_VERSION)"
# Make sure Node binaries can be found (required to run npm).
# And this lets us invoke npm more simply too.
export PATH=/opt/elasticbeanstalk/node-install/node-v$EB_NODE_VERSION-linux-x64/bin:$PATH
if yarn -v; then
echo 'Yarn already installed.'
else
echo 'Installing yarn...'
npm install yarn -g
fi
Solution 5
Since get-config
is no longer present in the new Amazon Linux 2 platform, we had to figure another clean way to do this, and came up with the following :
container_commands:
01_npm_install_yarn:
command: "npm install -g yarn"
10_yarn_install:
command: 'PATH="$PATH:$(dirname $(readlink $(which node)))" yarn install'
You may want to put the PATH=
logic in a script and call it before every yarn command, to have clean command:
instructions in your extentions.
Also, note that if you install yarn
using the yum package manager, you completely break the NodeJS version management provided by Beanstalk (since it the black magic running behind make some symlinks in /bin
and /usr/bin
).
Jiew Meng
Web Developer & Computer Science Student Tools of Trade: PHP, Symfony MVC, Doctrine ORM, HTML, CSS, jQuery/JS Looking at Python/Google App Engine, C#/WPF/Entity Framework I hope to develop usable web applications like Wunderlist, SpringPad in the future
Updated on June 02, 2022Comments
-
Jiew Meng about 2 years
Isit possible to configure EBS to install my NodeJS application using yarn package manager instead of NPM?