Automattic/node-canvas

Build for AWS Lambda

schaq8 opened this issue ยท 40 comments

I'm a Linux & node noob. I'm trying to run FabricJS (which requires node-canvas) in AWS Lambda. I've been able to follow the instructions to get up and running on an AWS Linux EC2, however, Lambda has me at my wits end. Anyone have any tips or pointers on how to get this compiled for AW Lambda?

This is actually a use case for me as well. I hope to try this this weekend and will let you know what I find. I think you'll have to bundle the SOs and change bindings.gyp to point to them.

Zach, I'd be so grateful!

On Thu, Nov 26, 2015 at 12:20 AM, Zach Bjornson notifications@github.com
wrote:

This is actually a use case for me as well. I hope to try this this
weekend and will let you know what I find. I think you'll have to bundle
the SOs and change bindings.gyp to point to them.

โ€”
Reply to this email directly or view it on GitHub
#680 (comment)
.

Didn't find time this weekend, and not sure when I'll get to this. If you want to try this on your own, you might check out the commits relating to the third bullet point here: #571

+1 I'm also interested in this.

Also related: #641 (although they're not statically linking). You might find some good stuff in the forks from the people commenting there and in 571.

+1 I'm also interested in this.

I was able to compile node-canvas and get it running on lambda by building dynamic and using rpath. Since lambda always runs in the same /var/task this makes it:

 export LDFLAGS=-Wl,-rpath=/var/task/

and then build normally.

You should also make sure you're compiling on the same AMI environment that lambda currently uses: http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html

@mankins could you provide some more info on how you dynamically build node-canvas?

Hey @jalieven here's some notes I made:

  1. Make sure you're compiling this on the same AMI that lambda currently uses:
    http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html
  2. Lambda runs at /var/task (that's the path when you unzip), so something.so at the root of the zip file will be at /var/task/something.so.

We then want to build our libraries using an "rpath":

 export LDFLAGS=-Wl,-rpath=/var/task/
  1. Compile libraries according to: https://github.com/Automattic/node-canvas/wiki/Installation---Amazon-Linux-AMI-%28EC2%29

You may want to set the prefix= ~/canvas to have all the files in one place.

  1. Install node-canvas with npm
  2. cd node_modules/canvas; node-gyp rebuild
  3. mkdir /pkg and cp the .so files (/canvas/lib/*.so) there, using -L to dereference symlinks.
  4. scp the pkg directory to the local lambda folder, possibly putting the files in the right places. (.so in root, node_modules/canvas with other libs). You'll probably want to rearrange this.

Good luck!

@mankins many thanks for your notes. Works like a charm!

@mankins Can you provide more details about the process?
I tried to follow your steps, but I think I miss something, because I am not able to make it work.
I got this error in AWS lambda:

{
"errorMessage": "libpng16.so.16: cannot open shared object file: No such file or directory",
"errorType": "Error",
"stackTrace": [
"Module.load (module.js:356:32)",
"Function.Module._load (module.js:312:12)",
"Module.require (module.js:364:17)",
"require (module.js:380:17)",
"Object. (/var/task/node_modules/canvas/lib/bindings.js:2:18)",
"Module._compile (module.js:456:26)",
"Object.Module._extensions..js (module.js:474:10)",
"Module.load (module.js:356:32)",
"Function.Module._load (module.js:312:12)",
"Module.require (module.js:364:17)"
]
}

My file structure (the zip that I upload to AWS Lambda) has the next structure:

  • Canvas.js
  • node_modules folder
  • pkg folder (with the *.so items, including libpng16.so.16)

In the AWS AMI instance that I am using to generate the zip file (same than you provide in your link), if I go to canvasexample/node_modules/canvas, and execute

ldd build/Release/canvas.node

The result that I get is:

linux-vdso.so.1 => (0x00007fff50dec000)
libpixman-1.so.0 => /usr/local/lib/libpixman-1.so.0 (0x00007fc31c71e000)
libcairo.so.2 => /usr/local/lib/libcairo.so.2 (0x00007fc31c418000)
libpng16.so.16 => /usr/local/lib/libpng16.so.16 (0x00007fc31c1e8000)
libjpeg.so.8 => /usr/local/lib/libjpeg.so.8 (0x00007fc31bfae000)
libgif.so.4 => /usr/lib64/libgif.so.4 (0x00007fc31bd9d000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fc31ba98000)
libm.so.6 => /lib64/libm.so.6 (0x00007fc31b796000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fc31b57f000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc31b363000)
libc.so.6 => /lib64/libc.so.6 (0x00007fc31afa1000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc31cbe0000)
libfontconfig.so.1 => /usr/lib64/libfontconfig.so.1 (0x00007fc31ad6b000)
libfreetype.so.6 => /usr/local/lib/libfreetype.so.6 (0x00007fc31aade000)
libxcb-shm.so.0 => /usr/lib64/libxcb-shm.so.0 (0x00007fc31a8dc000)
libxcb-render.so.0 => /usr/lib64/libxcb-render.so.0 (0x00007fc31a6d2000)
libxcb.so.1 => /usr/lib64/libxcb.so.1 (0x00007fc31a4b5000)
libXrender.so.1 => /usr/lib64/libXrender.so.1 (0x00007fc31a2ac000)
libX11.so.6 => /usr/lib64/libX11.so.6 (0x00007fc319f70000)
libXext.so.6 => /usr/lib64/libXext.so.6 (0x00007fc319d5e000)
libz.so.1 => /lib64/libz.so.1 (0x00007fc319b48000)
librt.so.1 => /lib64/librt.so.1 (0x00007fc31993f000)
libSM.so.6 => /usr/lib64/libSM.so.6 (0x00007fc319738000)
libICE.so.6 => /usr/lib64/libICE.so.6 (0x00007fc31951c000)
libexpat.so.1 => /lib64/libexpat.so.1 (0x00007fc3192f2000)
libXau.so.6 => /usr/lib64/libXau.so.6 (0x00007fc3190ef000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fc318eea000)
libuuid.so.1 => /lib64/libuuid.so.1 (0x00007fc318ce6000)

That I guess is not correct, because (If I understand), libpng16.so.16 and the other dependencies should point to my pkg folder (may be something like "/var/task/pkg/libpng16.so.16") , that is the same I will upload to Lambda, and same that would be executed, right? (I also tried to follow another similar issue in Package pre-compiled binaries with node-canvas for downstream consumers #641.

Any help is very very welcome!

Thank you very much!

It sounds like you need to use the -rpath=/var/task/ of -rpath=/var/task/pkg ... you're basically baking in a search path for dynamic libs (.so) and so if you put them in pkg, you'll need to compile them that way.

Thanks! I arranged to make it work in the way you were describing.

I will continue playing with this "rpath" option!

Thanks again!

I followed the process outlined by @mankins and created a GitHub repo with the compiled shared object (see src/*.so.*) files and an example with this working. Hope someone else finds this useful.

Following @webseed notes I managed to get camanJS library working on AWS Lambda so here it it helps somebody.

@mankins I'm sure i'm missing something very basic, but when I follow those instructions I don't seem to end up with any .so files in the lib directory, just .js ones. Any pointers would be great. here is the console output...

[ec2-user@ip-172-31-30-105 canvas]$ export LDFLAGS=-Wl,-rpath=/var/task/
[ec2-user@ip-172-31-30-105 canvas]$ cd node_modules/canvas/
[ec2-user@ip-172-31-30-105 canvas]$ node-gyp rebuild
gyp info it worked if it ends with ok
gyp info using node-gyp@3.3.1
gyp info using node@4.4.4 | linux | x64
gyp info spawn /usr/bin/python
gyp info spawn args [ '/usr/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args   'binding.gyp',
gyp info spawn args   '-f',
gyp info spawn args   'make',
gyp info spawn args   '-I',
gyp info spawn args   '/canvas/node_modules/canvas/build/config.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/usr/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/home/ec2-user/.node-gyp/4.4.4/include/node/common.gypi',
gyp info spawn args   '-Dlibrary=shared_library',
gyp info spawn args   '-Dvisibility=default',
gyp info spawn args   '-Dnode_root_dir=/home/ec2-user/.node-gyp/4.4.4',
gyp info spawn args   '-Dnode_gyp_dir=/usr/lib/node_modules/node-gyp',
gyp info spawn args   '-Dnode_lib_file=node.lib',
gyp info spawn args   '-Dmodule_root_dir=/canvas/node_modules/canvas',
gyp info spawn args   '--depth=.',
gyp info spawn args   '--no-parallel',
gyp info spawn args   '--generator-output',
gyp info spawn args   'build',
gyp info spawn args   '-Goutput_dir=.' ]
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
make: Entering directory `/canvas/node_modules/canvas/build'
  SOLINK_MODULE(target) Release/obj.target/canvas-postbuild.node
  COPY Release/canvas-postbuild.node
  CXX(target) Release/obj.target/canvas/src/Canvas.o
In file included from ../src/PNG.h:3:0,
                 from ../src/Canvas.cc:8:
/usr/include/libpng12/png.h:2657:31: warning: invalid suffix on literal; C++11 requires a space between literal and identifier [-Wliteral-suffix]
        fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
                               ^
/usr/include/libpng12/png.h:2665:31: warning: invalid suffix on literal; C++11 requires a space between literal and identifier [-Wliteral-suffix]
        fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
                               ^
/usr/include/libpng12/png.h:2673:31: warning: invalid suffix on literal; C++11 requires a space between literal and identifier [-Wliteral-suffix]
        fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
                               ^
  CXX(target) Release/obj.target/canvas/src/CanvasGradient.o
  CXX(target) Release/obj.target/canvas/src/CanvasPattern.o
  CXX(target) Release/obj.target/canvas/src/CanvasRenderingContext2d.o
  CXX(target) Release/obj.target/canvas/src/color.o
  CXX(target) Release/obj.target/canvas/src/Image.o
  CXX(target) Release/obj.target/canvas/src/ImageData.o
  CXX(target) Release/obj.target/canvas/src/init.o
  CXX(target) Release/obj.target/canvas/src/FontFace.o
  SOLINK_MODULE(target) Release/obj.target/canvas.node
  COPY Release/canvas.node
make: Leaving directory `/canvas/node_modules/canvas/build'
gyp info ok 
[ec2-user@ip-172-31-30-105 canvas]$ ls
binding.gyp  build  History.md  index.js  lib  node_modules  package.json  pkg  Readme.md  src  util
[ec2-user@ip-172-31-30-105 canvas]$ cd lib
[ec2-user@ip-172-31-30-105 lib]$ ls
bindings.js  canvas.js  context2d.js  image.js  jpegstream.js  pngstream.js

@ncgonz doesn't look like you're compiling the libraries. (You missed the first step?) Have a look at @webseed's repo https://github.com/WebSeed/node-canvas-aws-lambda-example where it's been done for us.

@mankins I looked into using that, he seems to have compiled against node version 0.10, which I cannot use. I have a dependency on jsdom, which requires node 4.3. I finally got everything compiled last night, and now have everything running on lambda. Hooray! Thanks for the pointers

Just created a gulp plugin to automate deployment of node-canvas in aws lambda which would handle both nodejs 0.10 and nodejs 4.3. jic if someone needs, https://www.npmjs.com/package/aws-lambda-node-canvas.

Hi...I am having the same problem. Am I missing something here?
Lambda runs on a system that will take care of the executing our package and running simultaneously many processes,etc. (I dont know what system is that).

@mankins : I just couldn comprehend this "Make sure you're compiling this on the same AMI that lambda currently uses".

Where can I get this info about the AMI that my Lambda function uses? Do I get a console for AMI where I can compile?

I have a few EC2 instances.Do I have to create an AMI for a particular EC2 instance? How to link my Lambda function with this AMI?

I know this may sound silly but I am really confused .

@abhi06991 you need to create EC2 instance with ami that lambda currently uses (http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) then ssh there and compile your thing
[you cannot ssh to lambda]

Hey guys, I followed the instructions and everything is working fine except Font Rendering. No font is rendering and Paths to font folders are correct,I have verified it.

I have included the following .so files:

libcairo.so.2
libfreetype.so.6
libgif.so.7
libjpeg.so.8
libpixman-1.so.
libpng16.so.16

Do I have to include some other .so files?

@abhi06991 you probably want to do cp -L /canvas/lib/*.so.* /your/folder instead

@navihtot I found your how-to notes super helpful, thanks!

@timsvoice np, glad that it helped somebody :)

Anyone managed to recently run everything successfully in Lambda? I'm using node-canvas through chartjs-node to render charts, I'm almost there but stuck on font rendering...

Basically the text is rendered as blocks, as if the font was not found.

By the way, in case anyone needs it, here's the full list of commands I ran in a Linux AMI (the one that https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html shows, currently 6.10)

Steps to build node-canvas for Lambda usage

  1. Create an AWS EC2 Instance (you can use the AWS Web Console) t2.micro based on the AMI from the link above
  2. SSH into it (you need the pem you created with it)
  3. Run the following commands, I suggest 1 by 1 to know if an error happened
export LDFLAGS=-Wl,-rpath=/var/task/
sudo yum groupinstall "Development Tools" -y
sudo yum install fontconfig-devel.x86_64 -y
sudo yum erase cairo -y

export PKG_CONFIG_PATH='/usr/local/lib/pkgconfig'
export LD_LIBRARY_PATH='/usr/local/lib':$LD_LIBRARY_PATH

sudo yum -y install zlib-devel

curl -L http://downloads.sourceforge.net/libpng/libpng-1.6.21.tar.xz -o libpng-1.6.21.tar.xz
tar -Jxf libpng-1.6.21.tar.xz && cd libpng-1.6.21
./configure --prefix=/home/ec2-user/canvas
make
sudo make install
cd ..

curl http://www.ijg.org/files/jpegsrc.v8d.tar.gz -o jpegsrc.tar.gz
tar -zxf jpegsrc.tar.gz && cd jpeg-8d/
./configure --disable-dependency-tracking --prefix=/home/ec2-user/canvas
make
sudo make install
cd ..

curl -L http://www.cairographics.org/releases/pixman-0.34.0.tar.gz -o pixman-0.34.0.tar.gz
tar -zxf pixman-0.34.0.tar.gz && cd pixman-0.34.0/
./configure --prefix=/home/ec2-user/canvas
make
sudo make install
cd ..

curl -L http://download.savannah.gnu.org/releases/freetype/freetype-2.6.tar.gz -o freetype-2.6.tar.gz
tar -zxf freetype-2.6.tar.gz && cd freetype-2.6/
./configure --prefix=/home/ec2-user/canvas
make
sudo make install
cd ..

curl https://www.freedesktop.org/software/fontconfig/release/fontconfig-2.12.0.tar.bz2 -o fontconfig.gz

sudo yum install libpng-devel -y

curl -L http://cairographics.org/releases/cairo-1.14.6.tar.xz -o cairo-1.14.6.tar.xz
tar -Jxf cairo-1.14.6.tar.xz && cd cairo-1.14.6
PKG_CONFIG_PATH=/home/ec2-user/canvas/lib/pkgconfig
PKG_CONFIG=/home/ec2-user/canvas/lib/pkgconfig
./configure --disable-dependency-tracking --without-x --prefix=/home/ec2-user/canvas
make
sudo make install
cd ..

sudo yum install giflib-devel -y

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.4/install.sh | bash

#After installing NVM you'll have to close your ssh session and reconnect.

nvm install 6.10

PKG_CONFIG_PATH=/home/ec2-user/canvas/lib/pkgconfig:/usr/local/lib/pkgconfig

# Gave up moment
sudo yum install cairo cairo-devel cairomm-devel libjpeg-turbo-devel pango pango-devel pangomm pangomm-devel giflib-devel -y

# Copy the pango dependencies
cp /usr/lib64/libpango*.so.* /home/ec2-user/canvas/lib/
cp /usr/lib64/libpango*.so /home/ec2-user/canvas/lib/

After that, you can npm install node-canvas into the ec2, and copy over SCP the folders in node_modules (should just be this library and the nan lib)
Copy that to your local node_modules before creating the zip (so whatever gets uploaded to Lambda, has these specially built modules)

I don't really understand why using "-rpath" and rebuilding the libraries from source should be required. According to the Lambda Documentation, LD_LIBRARY_PATH includes LAMBDA_TASK_ROOT (/var/task) and LAMBDA_TASK_ROOT/lib (/var/task/lib). So we should just be able to put libraries in there and have them found automatically.

I took the Lambda AMI and spun up a VM. I installed Node and development tools:

sudo yum groupinstall "Development Tools" -y
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.4/install.sh | bash

# Exit session and reopen here to make nvm available

nvm install 6.10

Then I installed node-canvas as you normally would:

sudo yum install cairo-devel libjpeg-turbo-devel giflib-devel pango-devel -y
npm install canvas@next

Then I copied the system libraries from /usr/lib64/ into a ./lib/ subdirectory in my Node project:

mkdir lib
cp /usr/lib64/{libpng12.so.0,libjpeg.so.62,libpixman-1.so.0,libfreetype.so.6,\
libcairo.so.2,libpango-1.0.so.0,libpangocairo-1.0.so.0,libpangoft2-1.0.so.0} lib/

I added an index.js to test Canvas with:

let
	{createCanvas} = require("canvas");

function hello(event, context, callback) {
	let
		canvas = createCanvas(200, 200),
		ctx = canvas.getContext('2d');

	// Write "Awesome!"
	ctx.font = '30px Impact';
	ctx.rotate(0.1);
	ctx.fillText('Awesome!', 50, 100);

	// Draw line under text
	let
		text = ctx.measureText('Awesome!');
	ctx.strokeStyle = 'rgba(0,0,0,0.5)';
	ctx.beginPath();
	ctx.lineTo(50, 102);
	ctx.lineTo(50 + text.width, 102);
	ctx.stroke();

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

module.exports = {hello};

And a serverless.yml file to deploy it to Amazon for me:

service: canvas-test

provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  region: us-east-1
  memorySize: 128
  timeout: 10

functions:
  hello:
    handler: index.hello

The resulting project structure:

โ”œโ”€โ”€ index.js
โ”œโ”€โ”€ lib
โ”‚   โ”œโ”€โ”€ libcairo.so.2
โ”‚   โ”œโ”€โ”€ libfreetype.so.6
โ”‚   โ”œโ”€โ”€ libjpeg.so.62
โ”‚   โ”œโ”€โ”€ libpango-1.0.so.0
โ”‚   โ”œโ”€โ”€ libpangocairo-1.0.so.0
โ”‚   โ”œโ”€โ”€ libpangoft2-1.0.so.0
โ”‚   โ”œโ”€โ”€ libpixman-1.so.0
โ”‚   โ””โ”€โ”€ libpng12.so.0
โ”œโ”€โ”€ node_modules
โ”‚   โ”œโ”€โ”€ canvas
โ”‚           ....
โ”‚   โ””โ”€โ”€ nan
โ”‚           ....
โ””โ”€โ”€ serverless.yml

I downloaded this entire folder to my local machine. Then I called serverless deploy to deploy it to Lambda, and serverless invoke --function hello and I got the successful result from it running on Lambda:

download

We could technically close this ticket and just leave that last comment as instructions for use in Lambda.

I went for the manual build because I didn't know where to take the .so and libs from. That is way easier, thanks @thenickdude

Closing since @thenickdude added instructions (thank you!).

Updated link is https://github.com/Automattic/node-canvas/wiki/Installation%3A-AWS-Lambda, which also includes the encouraging note:

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.

and cross-references #1231

Is it still the case that this works "out-of-the-box" I'm getting the following Lambda error:

{
    "errorType": "Error",
    "errorMessage": "libuuid.so.1: cannot open shared object file: No such file or directory",
    "trace": [
        "Error: libuuid.so.1: cannot open shared object file: No such file or directory",
        "    at Object.Module._extensions..node (internal/modules/cjs/loader.js:730:18)",
        "    at Module.load (internal/modules/cjs/loader.js:600:32)",
        "    at tryModuleLoad (internal/modules/cjs/loader.js:539:12)",
        "    at Function.Module._load (internal/modules/cjs/loader.js:531:3)",
        "    at Module.require (internal/modules/cjs/loader.js:637:17)",
        "    at require (internal/modules/cjs/helpers.js:22:18)",
        "    at Object.<anonymous> (/var/task/node_modules/canvas/lib/bindings.js:3:18)",
        "    at Module._compile (internal/modules/cjs/loader.js:701:30)",
        "    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)",
        "    at Module.load (internal/modules/cjs/loader.js:600:32)",
        "    at tryModuleLoad (internal/modules/cjs/loader.js:539:12)",
        "    at Function.Module._load (internal/modules/cjs/loader.js:531:3)",
        "    at Module.require (internal/modules/cjs/loader.js:637:17)",
        "    at require (internal/modules/cjs/helpers.js:22:18)",
        "    at Object.<anonymous> (/var/task/node_modules/canvas/lib/canvas.js:9:18)",
        "    at Module._compile (internal/modules/cjs/loader.js:701:30)"
    ]
}

Here's how to reproduce it:

1. Spin up an Amazon Linux 2 AMI:

I installed this one. amzn2-ami-hvm-2.0.20190313-x86_64-gp2. Then connect to the server over ssh.

2. Install node 10

curl --silent --location https://rpm.nodesource.com/setup_10.x | sudo bash -
sudo yum install -y nodejs

3. Install Serverless

sudo npm install --global serverless

4. Create project directory and install Canvas

mkdir test && cd test
npm install canvas@2.5.0 --save

5. Create Lambda handler index.js

let {createCanvas} = require("canvas");

function hello(event, context, callback) {
	let
		canvas = createCanvas(200, 200),
		ctx = canvas.getContext('2d');

	// Write "Awesome!"
	ctx.font = '30px Impact';
	ctx.rotate(0.1);
	ctx.fillText('Awesome!', 50, 100);

	// Draw line under text
	let text = ctx.measureText('Awesome!');
	ctx.strokeStyle = 'rgba(0,0,0,0.5)';
	ctx.beginPath();
	ctx.lineTo(50, 102);
	ctx.lineTo(50 + text.width, 102);
	ctx.stroke();

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

module.exports = {hello};

6. Create serverless.yml

service: canvas-test

provider:
  name: aws
  runtime: nodejs10.x
  stage: development
  region: us-east-1
  memorySize: 128
  timeout: 10

functions:
  hello:
    handler: index.hello

7. Deploy the function

serverless deploy

8. Invoke the function

serverless invoke --function hello

For some reason the /lib64 directory on Lambda for Amazon Linux 2 (Node 10) is incredibly sparse, much more empty than in the corresponding AMI they've published, which doesn't make sense to me.

I had to bundle the following libraries from Amazon Linux 2 with my function:

libEGL.so.1
libGL.so.1
libGLX.so.0
libGLdispatch.so.0
libICE.so.6
libSM.so.6
libX11.so.6
libXau.so.6
libXext.so.6
libXrender.so.1
libblkid.so.1
libcairo.so.2
libcroco-0.6.so.3
libexpat.so.1
libfontconfig.so.1
libfreetype.so.6
libfribidi.so.0
libgdk_pixbuf-2.0.so.0
libgif.so.7
libgio-2.0.so.0
libglib-2.0.so.0
libgmodule-2.0.so.0
libgobject-2.0.so.0
libgraphite2.so.3
libgthread-2.0.so.0
libharfbuzz.so.0
libjpeg.so.62
liblzma.so.5
libmount.so.1
libpango-1.0.so.0
libpangocairo-1.0.so.0
libpangoft2-1.0.so.0
libpixman-1.so.0
libpng16.so.16
librsvg-2.so.2
libthai.so.0
libuuid.so.1
libxcb-render.so.0
libxcb-shm.so.0
libxcb.so.1
libxml2.so.2

Notably, libuuid is not even included in the prebuilt Canvas. Is the Amazon Linux 2 image currently deployed on Lambda actually broken?

@thenickdude libuuid is included on my AMI

ll /usr/lib64/ | grep libuuid
lrwxrwxrwx  1 root root       16 Mar  8 19:58 libuuid.so.1 -> libuuid.so.1.3.0
-rwxr-xr-x  1 root root    20056 Jul 26  2018 libuuid.so.1.3.0

What is that size of all that? Copying all these files into your project will put you dangerously close the the max size of a Lambda function (250 MB).

Yes, it's in the AMI but it's not in the actual Lambda runtime environment. Run this on Lambda Node 10.x:

const fs = require('fs');

exports.handler = async (event, context) => {
  return fs.readdirSync("/usr/lib64").filter(p => p.match(/\.so/)).sort().join("\n");
};

This is the result:

ld-2.26.so
ld-linux-x86-64.so.2
libBrokenLocale-2.26.so
libBrokenLocale.so.1
libSegFault.so
libacl.so.1
libacl.so.1.1.0
libanl-2.26.so
libanl.so.1
libattr.so.1
libattr.so.1.1.0
libc-2.26.so
libc.so.6
libcap.so.2
libcap.so.2.22
libcidn-2.26.so
libcidn.so.1
libcom_err.so.2
libcom_err.so.2.1
libcrypto.so.1.0.2k
libcrypto.so.10
libdl-2.26.so
libdl.so.2
libffi.so.6
libffi.so.6.0.1
libform.so.6
libform.so.6.0
libformw.so.6
libformw.so.6.0
libfreebl3.chk
libfreebl3.so
libfreeblpriv3.chk
libfreeblpriv3.so
libgcc_s-7-20180303.so.1
libgcc_s.so.1
libgmp.so.10
libgmp.so.10.2.0
libgmpxx.so.4
libgmpxx.so.4.4.0
libgssapi_krb5.so.2
libgssapi_krb5.so.2.2
libgssrpc.so.4
libgssrpc.so.4.2
libk5crypto.so.3
libk5crypto.so.3.1
libkdb5.so.8
libkdb5.so.8.0
libkeyutils.so.1
libkeyutils.so.1.5
libkrad.so.0
libkrad.so.0.0
libkrb5.so.3
libkrb5.so.3.3
libkrb5support.so.0
libkrb5support.so.0.1
libm-2.26.so
libm.so.6
libmemusage.so
libmenu.so.6
libmenu.so.6.0
libmenuw.so.6
libmenuw.so.6.0
libmvec-2.26.so
libmvec.so.1
libncurses.so.6
libncurses.so.6.0
libncursesw.so.6
libncursesw.so.6.0
libnsl-2.26.so
libnsl.so.1
libnspr4.so
libnss_compat-2.26.so
libnss_compat.so.2
libnss_dns-2.26.so
libnss_dns.so.2
libnss_files-2.26.so
libnss_files.so.2
libnssckbi.so
libnssutil3.so
libp11-kit.so.0
libp11-kit.so.0.3.0
libpanel.so.6
libpanel.so.6.0
libpanelw.so.6
libpanelw.so.6.0
libpcprofile.so
libpcre.so.1
libpcre.so.1.2.0
libpcre16.so.0
libpcre16.so.0.2.0
libpcre32.so.0
libpcre32.so.0.0.0
libpcrecpp.so.0
libpcrecpp.so.0.0.0
libpcreposix.so.0
libpcreposix.so.0.0.1
libplc4.so
libplds4.so
libpopt.so.0
libpopt.so.0.0.0
libpthread-2.26.so
libpthread.so.0
libresolv-2.26.so
libresolv.so.2
librt-2.26.so
librt.so.1
libselinux.so.1
libsepol.so.1
libssl.so.1.0.2k
libssl.so.10
libstdc++.so.6
libstdc++.so.6.0.24
libtasn1.so.6
libtasn1.so.6.5.3
libthread_db-1.0.so
libthread_db.so.1
libtic.so.6
libtic.so.6.0
libtinfo.so.6
libtinfo.so.6.0
libutil-2.26.so
libutil.so.1
libverto.so.1
libverto.so.1.0.0
libz.so.1
libz.so.1.2.7
p11-kit-proxy.so
p11-kit-trust.so

The required libraries from my last post are about 100MB.

@thenickdude Thanks for your insight on this. I created a Lambda Layer which will address this issue.