How do I run `npm update -g npm` on Elastic Beanstalk?

送分小仙女□ 提交于 2019-12-03 08:46:56

It turns out this one is tricky, took a bit of digging and experimentation.

First, a quick bit about Elastic Beanstalk's lifecycle. There are several steps taken by AWS scripts running on each instance on deploy. For a Node.JS server, there are two of interest:

  • Install Node.JS
  • Run npm install

Installing Node.JS is where we can step in and do some magic. Most errors prompting the desire to do magic, or other things, to a beanstalk instance come from the npm install step.

Getting back on topic, the script AWS used to install node on beanstalk instances is /opt/elasticbeanstalk/hooks/appdeploy/pre/40install_node.sh. It usually looks like this:

#!/bin/bash

set -xe

/opt/elasticbeanstalk/containerfiles/ebnode.py --action node-install

This script installs a bunch of different node versions to /opt/elasticbeanstalk/node-install, including the one selected in the beanstalk configuration. Wouldn't it be nice to run npm update -g npm with one of the node versions sitting in that folder?

It turns out beanstalk supplies a mechanism to swap out files on each instance during deploy. Basically you configure YAML files in a .ebextensions folder in your app. There are two ways to reference the file contents, in line, or in an s3 bucket. I use the s3 bucket approach, giving a node.config YAML looking like this:

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/40install_node.sh" :
    mode: "000775"
    owner: root
    group: users
    source: https://s3.amazonaws.com/bucketname/40install_node.sh
    authentication: S3Access
Resources:
  AWSEBAutoScalingGroup:
    Metadata:
      AWS::CloudFormation::Authentication:
        S3Access:
          type: S3
          roleName: aws-elasticbeanstalk-ec2-role
          buckets: bucketname

Note the S3Access property. We keep the bucket private, granting access to the aws-elasticbeanstalk-ec2-role using IAM.

Now all we need is a version of 40install_node.sh running the npm update:

#!/bin/bash

set -xe

/opt/elasticbeanstalk/containerfiles/ebnode.py --action node-install

# Update npm
cd /opt/elasticbeanstalk/node-install/node-v0.12.2-linux-x64/bin/ && /opt/elasticbeanstalk/node-install/node-v0.12.2-linux-x64/bin/npm update npm -g

You can put any customization of your node install in this file as well. Just remember to keep an eye on the path to node, it will change as node versions go up in the beanstalk configuration.

If you don't want to add a script on to S3, you can simply put the following in your .ebextensions, assuming you're running node v12, for other versions the path node-v0.12.6-linux-x64 will be different.

commands:
    01-updatenpmv3:
        command: PATH=$PATH:/opt/elasticbeanstalk/node-install/node-v0.12.6-linux-x64/bin/ && npm update -g npm
        cwd: /opt/elasticbeanstalk/node-install/node-v0.12.6-linux-x64/bin/

This should not be necessary. You can specify in your configuration what version of Nodejs you want to be running, and thus would be paired with the appropriate npm version. If you did want to have an older version of nodejs with a newer version of npm, then this exercise would be warranted.

In this case I would probably step on the npm install script in a file dropped into the .ebextensions folder (e.g. 00_default.config):

 files:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/50npm.sh":
    mode: "000755"
    owner: root
    group: users
    content: |
      #!/bin/bash
      #==============================================================================
      # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
      #
      # Licensed under the Amazon Software License (the "License"). You may not use
      # this file except in compliance with the License. A copy of the License is
      # located at
      #
      #       http://aws.amazon.com/asl/
      #
      # or in the "license" file accompanying this file. This file is distributed on
      # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or
      # implied. See the License for the specific language governing permissions
      # and limitations under the License.
      #==============================================================================

      set -xe

      /opt/elasticbeanstalk/containerfiles/ebnode.py --action npm-install

      # Update npm
      cd /opt/elasticbeanstalk/node-install/CURRENTNODEVERSIONHERE/bin/ && /opt/elasticbeanstalk/node-install/CURRENTNODEVERSIONHERE/bin/npm update npm -g

Replace CURRENTNODEVERSIONHERE with the correct path/version for your setup.

These are the available versions I see on my instances. You'll want to check your own resources to see what you're working with.

Location: /opt/elasticbeanstalk/node-install

  • node-v0.10.46-linux-x64
  • node-v0.12.15-linux-x64
  • node-v0.8.28-linux-x64
  • node-v4.4.6-linux-x64
  • node-v5.12.0-linux-x64
  • node-v6.2.2-linux-x64
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!