Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

node.js - How can I install GraphicsMagick or ImageMagick on AWS Lambda?

I am using the gm package for Node.js along with the default ImageMagick installation that is available on AWS Lambda.

const gm = require('gm').subClass({ imageMagick: true });

For some reason, the resize functionality fails for certain images.

I created an EC2 instance with Amazon Linux AMI (ami-hvm-2016.03.3.x86_64-gp2). I installed the (old) 6.x version of ImageMagick that is available from yum. When I run my script with that install on the EC2 instance, it reproduces the failure I see when the code runs on Lambda, confirming it is something with this version of IM that is causing the failure.

If I install GraphicsMagick with sudo yum install GraphicsMagick. This allows my script to perform the resizes without error.

const gm = require('gm').subClass({ imageMagick: false });

However, I'm not sure how to bundle this in my deploy with serverless. If I install GraphicsMagick to the same folder as the script with sudo yum --installroot=/var/task install GraphicsMagick, and run my script using this require statement instead:

const gm = require('gm').subClass({ imageMagick: false, appPath: './usr/bin/' });

The resizes work when I run my script on the EC2 instance. But when I deploy with serverless, and the script runs in Lambda, the executable appears to be broken. gm fails with the following error on a call to gm(buffer).size(/*...*/).

could not get the image size: ERR: {"code":"EPIPE","errno":"EPIPE","syscall":"write"}

How can I build a version of ImageMagick or GraphicsMagick that can be deployed with serverless?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I spun up the latest aws linux and ran the commands below.

yum -y install gcc-c++ libpng-devel libjpeg-devel libtiff-devel wget
wget https://downloads.sourceforge.net/project/graphicsmagick/graphicsmagick/1.3.26/GraphicsMagick-1.3.26.tar.gz
tar zxvf GraphicsMagick-1.3.26.tar.gz
cd GraphicsMagick-1.3.26
./configure --prefix=/var/task/graphicsmagick --enable-shared=no --enable-static=yes
make
sudo make install
tar zcvf ~/graphicsmagick.tgz /var/task/graphicsmagick/

I scp the dir down into my local and threw it in the package to be zipped and deployed. My layout is similar to the aws repo code linked, but modified for serverless.

Lambda code:

// graphicsmagick dir is at the root of my project
const BIN_PATH = process.env['LAMBDA_TASK_ROOT'] + "/graphicsmagick/bin/";
const Gm = require('gm').subClass({ appPath: BIN_PATH });

// below is inside the handler
process.env['PATH'] = process.env['PATH'] + ':' + BIN_PATH;

serverless.yml

package:
  artifact: /path/to/function.zip

I use the artifact and build my own zip. If you run into the issue below I suggest you do that. https://github.com/serverless/serverless/issues/3215

# -y to keep the symlinks and thus reduce the size from 266M to 73M
cd lambda && zip -FS -q -r -y ../dist/function.zip *

Ideas grabbed from:

https://gist.github.com/bensie/56f51bc33d4a55e2fc9a

https://github.com/awslabs/serverless-image-resizing

Edit: Might want to also check out lambda layers. May only need to do this kind of thing once.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...