自定义AWS ElasticBeanstalk NodeJS安装(使用yarn)



是否可以配置EBS以使用yarn包管理器而不是NPM安装我的NodeJS应用程序?

我已经找到了一种方法,但有点麻烦。

  1. 创建一个.ebextensions/yarn.config文件(名称不必是"yarn"。)
  2. 将此内容放入文件:

    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;
    

这个扩展创建了一个文件,它可以做3件事:

  1. 安装节点
  2. 安装纱线
  3. 使用yarn安装node_modules

为了使Elastic Beanstalk在运行npm install之前先运行yarn install,文件是在/opt/elasticbeanstalk/hooks/appdeploy/pre下创建的。这将文件转换为预部署挂钩,这意味着Elastic Beanstalk将在部署的第一阶段运行它。默认情况下,该目录中还有另一个名为50npm.sh的文件,它运行npm install。由于Elastic Beanstalk按字母顺序运行该目录中的文件,49yarn.sh(我们的文件)将在50npm.sh(默认文件)之前运行,导致yarn installnpm install之前运行。

一个潜在的问题是,在部署阶段的这一点上,在Elastic Beanstalk UI中设置的环境变量(在Configuration>Software Configuration下)不可用。如果您有一个用于安装专用npm模块的npm-auth令牌,这将是一个大问题。

另一个潜在的问题是,这是手动安装节点的,因此您在Elastic Beanstalk UI中指定的"节点版本"(在Configuration>Software Configuration下)对应用程序使用的节点版本没有影响;您需要在此扩展中指定它。Elastic Beanstalk的50npm.sh既安装节点又运行npm install。由于我们必须在该文件运行之前运行yarn install,所以我们还必须手动安装节点。然后,当Elastic Beanstalk去安装节点时,它检测到节点已经安装,但没有验证它是正确的版本,因此跳过节点安装。

供参考,纱线安装说明来自此处:https://yarnpkg.com/docs/install#linux-选项卡

我在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"

我提出的这种方式仍然可以通过Elastic Beanstalks Dashboard控制节点版本。

谢谢你的提问!如果没有它,就不可能找到这个解决方案: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;

不得不重新审视这一点,因为我们无法弄清楚为什么我们被困在节点8上,尽管我们在EB UI中将其设置为节点12。似乎如果你安装了一个全局节点,它会覆盖版本设置。这不是安装全局节点,而是使用Elastic Beanstalk节点安装并将其添加到路径中。您必须在yarn安装脚本开始时再次添加PATH,但这似乎是使用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

防止EB运行npm install的一个简单方法是在prebuild挂钩中创建一个空的node_modules文件夹:

编辑your_project/.platform/hooks/prebuild/prevent-npm.sh:

#!/bin/bash
# EB build scripts will not install using npm if node_modules folder exists
mkdir node_modules

这样,EB仍然会安装Node.js,所以你不必自己安装。但当node_modules存在时,它将跳过npm install

然后在predeploy钩子内,您可以运行yarn。如果你运行的是Node.js 16或更新版本,你可以使用corepack yarn,它就会正常工作(你不必从yum、npm或任何其他地方安装yarn。)

编辑your_project/.platform/hooks/predeploy/yarn.sh:

#!/bin/bash
corepack yarn

请确保在您的项目中也在confighooks下创建符号链接,否则在更改配置(例如更新环境值)时将无法构建:

mkdir -p .platform/confighooks/{prebuild,predeploy}
ln -s ../../hooks/predeploy/yarn.sh .platform/confighooks/predeploy/yarn.sh
ln -s ../../hooks/prebuild/prevent-npm.sh .platform/confighooks/prebuild/prevent-npm.sh

由于get-config在新的AmazonLinux2平台中不再存在,我们不得不想出另一种干净的方法来做到这一点,并提出了以下内容:

container_commands:
01_npm_install_yarn:
command: "npm install -g yarn"
10_yarn_install:
command: 'PATH="$PATH:$(dirname $(readlink $(which node)))" yarn install'

您可能希望将PATH=逻辑放在脚本中,并在每个yarn命令之前调用它,以便在扩展中有干净的command:指令。

此外,请注意,如果使用yum软件包管理器安装yarn,则会完全破坏Beanstalk提供的NodeJS版本管理(因为它背后的黑魔法在/bin/usr/bin中创建了一些符号链接)。

最新更新