Aws-cdk: Code.fromAsset Bundling for NodeJS uses Wrong User

Created on 24 Jun 2020  路  16Comments  路  Source: aws/aws-cdk

When using the bundling option to provide Lambda code, the default behaviour for NODEJS based runtimes is broken, since it's using a non-root user within the Docker container. It can be manually fixed by providing root as user as part of the bundling options.

Reproduction Steps

    new lambda.Function(this, 'Handler', {
      code: lambda.Code.fromAsset('/path/to/lambda/folder', {
        bundling: {
          image: lambda.Runtime.NODEJS_12_X.bundlingDockerImage,
          command: [
            'bash', '-c', [
              `cp -R /asset-input/* /asset-output/`,
              `cd /asset-output`,
              `npm install`
            ].join(' && ')
          ],
        },
      }),
      runtime: lambda.Runtime.NODEJS_12_X,
      handler: "index.handler",
    });

Error Log

Failed to run bundling Docker image for asset Foo: Error: [Status 243] stdout:


stderr: npm ERR! correctMkdir failed to make directory /.npm/_locks
npm WARN [email protected] No description
npm WARN [email protected] No repository field.

npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /.npm
npm ERR! errno -13
npm ERR!
npm ERR! Your cache folder contains root-owned files, due to a bug in
npm ERR! previous versions of npm which has since been addressed.
npm ERR!
npm ERR! To permanently fix this problem, please run:
npm ERR!   sudo chown -R 501:20 "/.npm"
Subprocess exited with error 1

Environment

  • CLI Version : 1.46.0 (build 63860b2)
  • Framework Version:1.46.0
  • Node.js Version: v13.8.0
  • OS : macOS Catalina
  • Language (Version): all

Other

Since the fix is passing user: 'root' as argument, I think this change is causing the behaviour https://github.com/aws/aws-cdk/pull/8492


This is :bug: Bug Report

@aws-cdassets bug efforsmall p1

All 16 comments

@eladb We don't want to have bundled assets owned by root (see #8489) but at the same time we should allow running the container as root...

Need to try this but how about running the image again with command: ['sh', '-c', 'chmod -R 777 /asset-output'] after this (both runs would run as root)?

https://github.com/aws/aws-cdk/blob/cc5bf4ec55506061f4e60d582859a6f9b5e3bd50/packages/%40aws-cdk/core/lib/asset-staging.ts#L171-L181

@jogold not sure how setting all files to 777 under /asset-output would solve this problem

@jogold not sure how setting all files to 777 under /asset-output would solve this problem

If we go back to running the container as root we will have content owned by root in /asset-output (#8489). A solution could be to run as root and then run again as root to change permissions (hacky?).

Oh, men! I would have saved a lot of time with the fix proposed by @jogold

After enabling debug in docker daemon, running lambda docker images by hand, I figured this.

At least in a Python project using cdk 1.47.1, chmod -R 777 .cdk.staging after cdk synth --staging allowed me to run successfully 'sam local invoke' a lambda bundling asset code

I am getting similar error but for go-1-x lambda
Failed to run bundling Docker image for asset xxx Error: spawnSync docker ENOENT

I am getting similar error but for go-1-x lambda
Failed to run bundling Docker image for asset xxx Error: spawnSync docker ENOENT

This error message means that docker is not available. You can make docker available in your environment, use the CDK_DOCKER env var or use the new "local bundling" alternative (the latest will be available in the next release)

This error message means that docker is not available. You can make docker available in your environment, use the CDK_DOCKER env var

@jogold I don't understand what you mean by this. The environment variable takes key and value. You have mentioned only 1 of them(CDK_DOCKER). And my guess is CDK_DOCKER is the key and its value is missing. I am new to this and was trying to follow building go lambda inside docker tutorial.

or use the new "local bundling" alternative (the latest will be available in the next release)

The alternative you suggested has very little explanation and no sample code. But I am guessing you are recommending building lambda on my local machine. Which I already do with Taskfile and deploy zip file. This solution has been working for me.

Between local bundling and docker bundling I feel docker solution is better solution. So I would like to figure out how to make it work. So if you could provide sample code for golang lambda then it would be great.

Docker was working with Cloud9 editor but I didn't really like Cloud9 and I moved to using VS Code and sshing into EC2 instance. Since then it stopped working. I guess I need that CDK_DOCKER env variable that is missing.

Can you check if docker is available/installed in your environment and in your PATH? Are you able to run docker in your EC2 instance?

@jogold
No its not installed/available. But there is special docker version for AWS right. This is directly going to cloudformation template. Is there CDK way to install it instead? Or should I just install regular Ubuntu version instead? I am running Ubuntu 20.04 on EC2

Yes you have to have Docker installed, so in your case Docker for Ubuntu

@jogold Thanks for patiently helping me out. I don't know what I did. I copy pasted lot of code from lot of google search. I don't know what it means but the net result is I have successfully build lambda inside docker container and deployed to aws. I tested api to verify if lambda is actually been deployed. Also after deploy I tried cdk diff and it actually printed There were no differences. It does bundling each time I do cdk diff but also knows if code has changed or not.

I suppose that means this issue is resolved. Thanks for helping out @jogold.

I suppose that means this issue is resolved. Thanks for helping out @jogold.

@nija-at I don't think because @apoorvmote issue wasn't related to the original issue, created by bundling assets owned by root according to @jogold

Hi, i am a newby. Please be patient with me.
The following bundling command worked for my lambda functions.

const command = [
  'bash', '-c',
  `cp -aur . /asset-output &&
   cd /asset-output &&
   mkdir .npm &&
   export npm_config_cache=.npm &&
   npm install`,
];

I changed the cache location to a folder created by the current user.

The missing thing for me was it needs to be run by root.

const myLayer = new LayerVersion(this, 'my-layer', {
  code: Code.fromAsset(assetPath, {
    assetHashType: cdk.AssetHashType.BUNDLE,
    bundling: {
      user: 'root',
...

I am back at the same issue.
1) I switched from intel computer to arm computer. And docker has some issue running intel container inside arm computer. So its docker issue not cdk issue.
2) I switched from golang lambda to nodejs lambda so now this issue interests me.

Was this page helpful?
0 / 5 - 0 ratings