Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not working on AWS Lambda #1231

Closed
yellowmamba opened this Issue Aug 27, 2018 · 5 comments

Comments

Projects
None yet
4 participants
@yellowmamba
Copy link

yellowmamba commented Aug 27, 2018

Issue or Feature

I installed prebuilt 2.0 to work with my lambda function. It works locally but when I deploy it to Lambda, it throws the following error from cloudwatch:

module initialization error: Error at Error (native) at Object.Module._extensions..node (module.js:597:18) at Module.load (module.js:487:32) at tryModuleLoad (module.js:446:12) at Function.Module._load (module.js:438:3) at Module.require (module.js:497:17) at require (internal/module.js:20:19) at Object.<anonymous> (/var/task/node_modules/canvas/lib/bindings.js:3:18

If I understand it correctly from this page. https://github.com/Automattic/node-canvas/wiki/Installation%3A-AWS-Lambda. 2.0 should work out of box, but apparently it doesn't. The example given in this doc indicates the code works with nodejs6.10, so I also tried to run it on nodejs6.10 on Lambda, didn't work. (I initially tried it on nodejs8.10, didn't work either)

Steps to Reproduce

handler.js

const { createCanvas } = require('canvas')
const canvas = createCanvas(200, 200)
const ctx = canvas.getContext('2d')

module.exports.index = function (event, context, callback) {
  console.log(event)
  ctx.font = '30px Impact'
  ctx.fillText('Awesome!', 50, 100)

  callback(null, '<img src="' + canvas.toDataURL() + '" />');
}

serverless.yml

service: my-service

provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  region: ap-southeast-2

functions:
  index:
    handler: handler.index

package.json

{
  "dependencies": {
    "canvas": "2.0"
  }
}

sls invoke works, but testing directly on Lambda doesn't.

Your Environment

  • Version of node-canvas (e.g. 1.4.0): canvas@2.0
  • Environment (e.g. node 4.2.0 on Mac OS X 10.8): aws nodejs6.10
@LinusU

This comment has been minimized.

Copy link
Collaborator

LinusU commented Aug 27, 2018

How are you packaging your app and sending it to Lambda? Maybe you are sending the macOS binary to the Lambda?

@jakelazaroff

This comment has been minimized.

Copy link

jakelazaroff commented Sep 2, 2018

I'm also experiencing this issue. I'm packaging my app with Webpack and deploying it with Apex. Using Node 8.10 and I've tried with both 1.x and 2.x versions of node-canvas.

I made an example project to isolate node-canvas. It works locally but not when invoked from the AWS web console. Here's the zip I uploaded, and here's
a gist of the project: https://gist.github.com/jakelazaroff/29e3e6d81c6cba1c6a8a10c09324c888

Edit: This Stack Overflow answer seems to indicate this is happening because the native bindings haven't been compiled for AWS Lambda. I went searching in the wiki, found the page for canvas-prebuilt, tried with that and got the same result. Next step is trying to build it myself, I guess?

@zbjornson

This comment has been minimized.

Copy link
Collaborator

zbjornson commented Sep 2, 2018

@jakelazaroff there's some info here: apex/apex#468. Sounds like you need to deploy from an AWS Linux AMI for any native addons to work.

If we switch to the approach of bundling the binaries for all platforms in the tarball, I think that lends itself to a runtime selection of the right binary.


Re-reading the Lambda documentation ... I didn't realize Lambda itself requires the ZIP with all dependencies, it's not a convenience option that Apex and Serverless are taking advantage of. GCF avoids this issue with native deps by running npm install on their servers for you.

@LinusU

This comment has been minimized.

Copy link
Collaborator

LinusU commented Sep 2, 2018

If we switch to the approach of bundling the binaries for all platforms in the tarball, I think that lends itself to a runtime selection of the right binary.

Yeah, this is probably a good approach 👍


@yellowmamba if you want a quick fix you can look at building the zip-file that you send to Lambda inside of Docker. That's what I'm doing in the scandium which I think is quite similar to apex.

The relevant code is here: https://github.com/LinusU/scandium/blob/master/lib/dockerfile.js

@jakelazaroff

This comment has been minimized.

Copy link

jakelazaroff commented Sep 3, 2018

I tried installing the library inside of Docker (thanks for the reference code @LinusU) and it works perfectly! Here's a gist with the working code. You can just run yarn prebuild to build the Docker image, yarn build to actually compile it, and then just zip up all the files and upload them to AWS. @yellowmamba check it out if you want a minimal example of a working setup.

I was going to suggest adding a caveat to this wiki page, but it looks like @zbjornson already added a link to this issue 😃 This can probably be closed now. Thank y'all for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.