'AWS Lambda execute shell npm install error

I'm trying to build a web app in AWS lambda and upload it to an S3 bucket. For that, I utilize child process, which is working fine locally.

exec('cd /tmp/ && npm ci && ng build --prod="true"', (error, stderr, stdout) => {
      if (error) {
        console.log(error);
        return reject(error);
        }
      });

I also tried using npm install instead of npm ci, in all cases it fails with the error:

"npm ERR! errno -30", "npm ERR! rofs EROFS: read-only file system, mkdir '/home/sbx_user1051'", "npm ERR! rofs Often virtualized file systems, or other file systems", "npm ERR! rofs that don't support symlinks, give this error.", "npm ERR! code EROFS", "npm ERR! syscall mkdir",

Command failed: cd /tmp/ && npm ci && ng build --prod="true"\nnpm ERR! code EROFS\nnpm ERR! syscall mkdir\nnpm ERR! path /home/sbx_user1051\nnpm ERR! errno -30\nnpm ERR! rofs EROFS: read-only file system, mkdir '/home/sbx_user1051'\nnpm ERR! rofs Often virtualized file systems, or other file systems\nnpm ERR! rofs that don't support symlinks, give this error.\nnpm ERR!

I understand that only the /tmp/ directory is writable in AWS Lambda. I just don't know how to tell npm to run in /tmp.

Any ideas?



Solution 1:[1]

Usually, people install everything during the build phase and then they zip it and deploy as a lambda function. AWS provides some example projects for doing exactly that https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html

Or with amplify https://aws.amazon.com/amplify/

With node there is also an option to use serverless https://stackify.com/aws-lambda-with-node-js-a-complete-getting-started-guide/

Or, now, you may also consider using docker https://aws.amazon.com/blogs/aws/new-for-aws-lambda-container-image-support/

Any of this can be prepared in a CI/CD pipeline (https://www.weave.works/blog/what-cicd-tool-should-i-use).

Generally, I would avoid self-modifying lambdas. That's hardly repeatable. One day one npm package will not be available for a minute, AWS will scale out your lambda and it will start failing and your whole application will crumble.

If your goal is to repeatedly build node apps in a lambda go the docker path, that has the most flexibility.

Solution 2:[2]

Hi I've successfully got npm working by setting NPM_CONFIG_USERCONFIG environment variable to /tmp/.npmrc and set npm cache directory to /tmp/.npm.

Like this:

  const dir = '/tmp/your_project_dir';
  process.env.NPM_CONFIG_USERCONFIG='/tmp/.npmrc';
  
  execSync(`npm config set cache /tmp/.npm`);
  execSync(`npm ci && npm run build`, {cwd: dir});

Also I found someone created a Lambda layer containing npm cli which can be used in non-nodejs Lambda environment. https://github.com/sambaiz/npm-lambda-layer

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 petrch
Solution 2 tmokmss