|
1 | | -# lambda-node-canvas |
2 | | -AWS Lambda blueprint for generating and manipulating graphics using node-canvas, a Cairo backed Canvas implementation for NodeJS by @Automattic. |
| 1 | +# Changes on this repository |
| 2 | + |
| 3 | +Due to the size of dependencies, i.e. node_modules folder, it is no longer available to edit any serverless app based on this blueprint using AWS Lambda inline editor with node-canvas version 2.0+. So, I update this repository as resource space for those who would like to use node-canvas in their AWS Lambda functions. |
| 4 | + |
| 5 | +In order to use node-canvas on AWS Lambda, there is an official guide from @Automattic. For native dependencies like libcairo.so.2 and others, you may use the files I uploaded to this repostory. |
| 6 | + |
| 7 | +# Getting node-canvas works on AWS Lambda |
| 8 | + |
| 9 | +Node canvas is a Cairo backed Canvas implementation for NodeJS by @Automattic. Following is the snapshot of Installation Guide from [official wiki](https://github.com/Automattic/node-canvas) last updated on Sep 3, 2018. |
| 10 | + |
| 11 | +**Canvas 2.0 and 1.6 works out-of-the-box on AWS Lambda thanks to prebuilds. However, you must build your Lambda ZIP file on Linux (or a Linux Docker container) so that the correct prebuilt binary is included.** See https://github.com/Automattic/node-canvas/issues/1231 for more info. |
| 12 | + |
| 13 | +The below instructions can be used for older versions or custom builds. |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +Lambda doesn't have the required libraries installed by default, but it can load them from either the `./` or `./lib` directories in your packaged function. |
| 18 | + |
| 19 | +Create an EC2 VM from the [the Lambda AMI](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html), we'll use this to build canvas and grab compatible libraries. |
| 20 | + |
| 21 | +Install Node and development tools: |
| 22 | + |
| 23 | +```bash |
| 24 | +sudo yum groupinstall "Development Tools" -y |
| 25 | +curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash |
| 26 | + |
| 27 | +# Exit SSH session and reopen here to make nvm available |
| 28 | + |
| 29 | +# Node 6.10: |
| 30 | +nvm install 6.10 |
| 31 | +# Or Node 8.10: |
| 32 | +nvm install 8.10 |
| 33 | +``` |
| 34 | + |
| 35 | +Install node-canvas as you normally would on Linux: |
| 36 | + |
| 37 | +```bash |
| 38 | +sudo yum install cairo-devel libjpeg-turbo-devel giflib-devel pango-devel -y |
| 39 | +npm install canvas@next |
| 40 | +``` |
| 41 | + |
| 42 | +Then copy the system libraries from `/usr/lib64/` into a `./lib/` subdirectory for your Lambda function: |
| 43 | + |
| 44 | +``` |
| 45 | +mkdir lib |
| 46 | +cp /usr/lib64/{libpng12.so.0,libjpeg.so.62,libpixman-1.so.0,libfreetype.so.6,\ |
| 47 | +libcairo.so.2,libpango-1.0.so.0,libpangocairo-1.0.so.0,libpangoft2-1.0.so.0} lib/ |
| 48 | +``` |
| 49 | + |
| 50 | +At this point you can package up the `node_modules` and `lib` directories and download them to your local machine. The `node_modules/canvas/build/Release/canvas.node` library has been built for the Lambda architecture, so don't overwrite it by rebuilding the canvas package on your local machine. |
| 51 | + |
| 52 | +Then you can add an `index.js` handler to test Canvas with: |
| 53 | + |
| 54 | +```js |
| 55 | +let |
| 56 | + {createCanvas} = require("canvas"); |
| 57 | + |
| 58 | +function hello(event, context, callback) { |
| 59 | + let |
| 60 | + canvas = createCanvas(200, 200), |
| 61 | + ctx = canvas.getContext('2d'); |
| 62 | + |
| 63 | + // Write "Awesome!" |
| 64 | + ctx.font = '30px Impact'; |
| 65 | + ctx.rotate(0.1); |
| 66 | + ctx.fillText('Awesome!', 50, 100); |
| 67 | + |
| 68 | + // Draw line under text |
| 69 | + let |
| 70 | + text = ctx.measureText('Awesome!'); |
| 71 | + ctx.strokeStyle = 'rgba(0,0,0,0.5)'; |
| 72 | + ctx.beginPath(); |
| 73 | + ctx.lineTo(50, 102); |
| 74 | + ctx.lineTo(50 + text.width, 102); |
| 75 | + ctx.stroke(); |
| 76 | + |
| 77 | + callback(null, '<img src="' + canvas.toDataURL() + '" />'); |
| 78 | +} |
| 79 | + |
| 80 | +module.exports = {hello}; |
| 81 | +``` |
| 82 | + |
| 83 | +You can now zip up this function and manually deploy it to Lambda (just set Node to 6.10 and the handler to `index.hello`), or you can deploy it using [Serverless](https://serverless.com/). For Serverless, add a `serverless.yml` file to the root of your project: |
| 84 | + |
| 85 | +``` |
| 86 | +service: canvas-test |
| 87 | +
|
| 88 | +provider: |
| 89 | + name: aws |
| 90 | + runtime: nodejs6.10 |
| 91 | + stage: dev |
| 92 | + region: us-east-1 |
| 93 | + memorySize: 128 |
| 94 | + timeout: 10 |
| 95 | +
|
| 96 | +functions: |
| 97 | + hello: |
| 98 | + handler: index.hello |
| 99 | +``` |
| 100 | + |
| 101 | +The resulting project structure: |
| 102 | + |
| 103 | +``` |
| 104 | +├── index.js |
| 105 | +├── lib |
| 106 | +│ ├── libcairo.so.2 |
| 107 | +│ ├── libfreetype.so.6 |
| 108 | +│ ├── libjpeg.so.62 |
| 109 | +│ ├── libpango-1.0.so.0 |
| 110 | +│ ├── libpangocairo-1.0.so.0 |
| 111 | +│ ├── libpangoft2-1.0.so.0 |
| 112 | +│ ├── libpixman-1.so.0 |
| 113 | +│ └── libpng12.so.0 |
| 114 | +├── node_modules |
| 115 | +│ ├── canvas |
| 116 | +│ .... |
| 117 | +│ └── nan |
| 118 | +│ .... |
| 119 | +└── serverless.yml |
| 120 | +``` |
| 121 | + |
| 122 | +Call `serverless deploy` to deploy it to Lambda, and `serverless invoke --function hello` to run it, and you should get back the HTML for this successful result: |
| 123 | + |
| 124 | + |
| 125 | + |
| 126 | +## Using newer versions of libcairo |
| 127 | + |
| 128 | +The version of Amazon Linux that Lambda uses includes libcairo v1.12, which produces noticeably poor results when downscaling images with `drawImage()`. This was fixed in Cairo v1.14. You can use the install instructions for EC2 ([[Installation - Amazon-Linux-AMI-(EC2)]]) to build libcairo 1.14 and libpixman 0.34 from source, and replace the `libcairo.so.2` and `libpixman-1.so.0` binaries in your Lambda's `lib` directory with the resulting libraries (you can find those built libraries in `/usr/local/lib`). |
| 129 | + |
| 130 | +However, due to the ordering of the directories in Lambda's `LD_LIBRARY_PATH` (`/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib`) the operating system's included libcairo and libpixman will be used instead of the copies in your Lambda's `lib` directory. To fix this you need to set LDFLAGS during canvas installation: |
| 131 | + |
| 132 | +```bash |
| 133 | +export LDFLAGS=-Wl,-rpath=/var/task/lib |
| 134 | +npm install canvas@next |
| 135 | +``` |
| 136 | + |
| 137 | +This will set the RPATH flags in the built `canvas.node` library to look for libraries in `/var/task/lib` first (your Lambda's bundled `lib` directory). Update the copy of `canvas.node` in your Lambda's `lib` directory with this newly-built version. |
0 commit comments