如何在AWS Lambda上安装GraphicsMagick或ImageMagick?

32
我正在使用Node.js的gm包以及AWS Lambda上可用的默认ImageMagick安装。但某些图像的调整大小功能会出现故障。
我创建了一个Amazon Linux AMI(ami-hvm-2016.03.3.x86_64-gp2)的EC2实例,并安装了从yum获取的(旧版)ImageMagick 6.x版本。当我在EC2实例上使用该安装运行脚本时,它会再现Lambda上运行代码时看到的故障,确认是这个IM版本导致了失败。
如果我使用sudo yum install GraphicsMagick安装GraphicsMagick,则可以使我的脚本执行调整大小操作而不会出错。但我不确定如何将其与serverless一起捆绑。
如果我使用sudo yum --installroot=/var/task install GraphicsMagick命令将GraphicsMagick安装到与脚本相同的文件夹中,并使用以下require语句运行脚本: const gm = require('gm').subClass({ imageMagick: false, appPath: './usr/bin/' }); 则在EC2实例上运行脚本时,调整大小操作可以正常工作。但是在使用serverless部署并在Lambda中运行脚本时,可执行文件似乎已损坏。 gm调用gm(buffer).size(/*...*/)时会出现以下错误: could not get the image size: ERR: {"code":"EPIPE","errno":"EPIPE","syscall":"write"} 如何构建可以部署到serverless的ImageMagick或GraphicsMagick版本?
7个回答

31

我启动了最新的AWS Linux并运行了下面的命令。

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/

我将目录scp到本地,然后将其放入打包、压缩和部署的软件包中。我的布局类似于链接的aws存储库代码,但进行了无服务器修改。

Lambda 代码:

// 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;

无服务器架构配置文件

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

我使用这个工具并创建了我的自定义压缩包。如果你遇到下面的问题,我建议你也这样做。 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 *

以下灵感来源:

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

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

编辑: 可能还需要查看Lambda层(Lambda layers)。只需要执行此类操作一次。


1
更改为./configure --prefix=/var/task/graphicsmagick --enable-shared=no --enable-static=yes - user732961
3
我正在处理依赖库的问题...当我在Lambda上运行gm时,例如找不到libjpeg.so.62。 - Michael Wiles
1
除了列出的软件包之外,我还需要安装targzipmake。另一个替代scp的选项是在主机上运行docker cp [container id]:/root/graphicsmagick.tgz ./ - Tuure
你在哪里运行这些命令?我创建了一个 Lambda 函数,它在本地运行良好,但给我同样的错误。你能具体说明一下你是如何在哪里运行这些命令的步骤吗? - Osama Khalid
我的简单 Lambda 函数的 serverless.yml 文件在哪里? - Osama Khalid
显示剩余2条评论

8
我曾经为此苦苦挣扎了几天,最终自己经历了整个过程,确实有效。
ImageMagick不再与Node.js 10.x运行时捆绑在一起。有三种方法可以使ImageMagick与您的Node.js 10.x函数配合使用:
1)打包依赖项并将其包含在上传的ZIP文件中(例如此文件)。

https://image-magick-example.s3-us-west-2.amazonaws.com/image-magick-example.zip

https://github.com/hmagdy/imagemagick-aws-lambda-Node.js10.x/tree/master/option1_image-magick-example-zip

但是有一个选项:您的Lambda函数“image-magick-example-zip-demo”的部署包太大,无法启用内联代码编辑。不过,您仍然可以调用该函数。

enter image description here

或者

2)创建或使用包含ImageMagick的Lambda层,方法如下:

clone git@github.com:hmagdy/imagemagick-aws-lambda-Node.js10.x.git
cd imagemagick-aws-lambda-2
start Docker services
make all

这将在构建文件夹内创建一个layer.zip。但是为了节省您的时间,这里有一个可以用来创建Lambda层的zip文件。

https://image-magick-layer.s3-us-west-2.amazonaws.com/layer.zip

创建图层时,请确保将Node.js 10.x添加为受支持的运行时。然后,您可以将函数设置为使用最新的Node.js 10.x,并添加您创建的图层。图像转换应该会再次正常工作!

enter image description here

然后您可以像这样创建您的 AWS Lambda 函数。

https://github.com/hmagdy/imagemagick-aws-lambda-Node.js10.x/tree/master/option2_image-magick-example-c_lib_layer/index.js

3) 使用带有 AWS Lambda Layers 的 NodeJS 运行环境 (npm),操作步骤如下:

此外,如果您想使用

const imageThumbnail = require('image-thumbnail');

并获得

Runtime.ImportModuleError: Error: Cannot find module 'image-thumbnail'

你应该遵循选项3:

https://github.com/hmagdy/imagemagick-aws-lambda-Node.js10.x/tree/master/option3_image-magick-example-npm_layer

受以下启发:

https://medium.com/@anjanava.biswas/nodejs-runtime-environment-with-aws-lambda-layers-f3914613e20e


1
我刚刚上传了图层(步骤2),它立即开始工作。非常感谢!做得很好。 - Jan Sila

7
如果你想处理图像缩放的话,可以看看serverless sharp image库,它使用了Sharp这个高性能的Node.js图像缩放库,与GM/IM相比,速度快3倍到5倍。虽然你没有提供足够的信息来确定它是否符合你的用例需求,但我还是想提一下,因为这个库让我迄今为止节省了很多AWS Lambda成本。
顺便说一句:我与该项目无关(但许可证都是MIT / Apache License 2.0)。

1
在切换之前请注意Sharp的限制:http://sharp.pixelplumbing.com/en/stable/api-input/#limitinputpixels 如果您想处理大型图像,这可能会成为一个问题。 - Zedzdead
Sharp也有同样的问题。你需要有docker来构建它。 - astroanu

1

所有依赖项都可以作为 AWS Lambda 函数的一部分打包并上传

您可以在 AWS Lambda 中使用大多数软件包,只要您将其适配到允许的大小限制中并上传 zip 文件。请查看 AWS Lambda 部署限制 部分。

此外,这是一个打包依赖项的示例(针对 Python 代码)https://dev59.com/xFoV5IYBdhLWcg3wmPpH#36093281


1
我已经在包中安装了ImageMagick,并且可以在node_modules文件夹中看到它。但是仍然出现相同的错误。在本地,我已经在Ubuntu上安装了ImageMagick,并且它可以正常工作。我不知道如何在Lambda环境中安装它。 - Osama Khalid
1
@OsamaKhalid,您不需要在lambda环境中进行安装,而是需要打包所有依赖项,例如在这种情况下,就是ImageMagick。请参考以下示例:https://dev59.com/xFoV5IYBdhLWcg3wmPpH#36093281 - Chenna V

1

对于node.js,您可以使用node-lambda,它使用docker镜像简化了打包过程:

node-lambda package -I lambci/lambda:build-nodejs6.10 -A . -x '*.lock *.zip'

-I参数将启动一个Docker镜像,并在您的项目中启动npm i,以便将二进制node_modules编译为正确的架构。


那么你如何使用无服务器进行部署?serverless deploy - Noah

0
如果您在本地设备上安装了Docker并将此命令添加到您的package.json中。
"dockerbuild": "rm -rf node_modules/gm && docker run -v \"$PWD\":/var/task lambci/lambda:build-nodejs8.10 npm install"

在部署应用之前,请运行npm run dockerbuild

您应该根据Lambda环境的版本更改节点版本。


-2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接