35

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

4

5 回答 5

30

我想出了一个办法,但它有点hacky。

  1. 创建一个.ebextensions/yarn.config文件。(名称不必是“纱线”。)
  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;
    

这个 ebextension 创建了一个文件,它做了 3 件事:

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

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

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

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

作为参考,纱线安装说明来自这里: https ://yarnpkg.com/docs/install#linux-tab

于 2017-02-07T17:29:48.800 回答
7

我按照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"
于 2017-05-08T19:33:39.197 回答
4

我想出的这种方式让您仍然可以通过 Elastic Beanstalks 仪表板控制节点版本。

谢谢这个问题!没有它就不可能得到这个解决方案: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;
于 2018-09-06T15:55:54.573 回答
3

不得不重新审视这一点,因为即使我们在 EB UI 中将其设置为节点 12,我们也无法弄清楚为什么会卡在节点 8 上。似乎如果您安装一个全局节点,它会覆盖版本设置。这不是安装全局节点,而是使用 Elastic Beanstalk 节点安装并将其添加到路径中。您必须在纱线安装脚本的开头再次添加 PATH,但这似乎是使用纱线的侵入性最小的方式。

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
于 2020-05-28T21:20:47.673 回答
1

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

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

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

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

于 2020-07-24T13:39:06.713 回答