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

How can I install GraphicsMagick or ImageMagick on AWS Lambda?

我正在使用 Node.js 的 gm 包以及 AWS Lambda 上可用的默认 ImageMagick 安装。

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

由于某种原因,某些图像的调整大小功能失败。

我使用 Amazon Linux AMI (ami-hvm-2016.03.3.x86_64-gp2) 创建了一个 EC2 实例。 我安装了(旧)6.x 版本的 ImageMagick,可从 yum 获得。当我 运行 我的脚本在 EC2 实例上安装时,它重现了我在 Lambda 上的代码 运行s 时看到的故障,确认是这个版本的 IM 导致了故障。

如果我用 sudo yum install GraphicsMagick 安装 GraphicsMagick。这允许我的脚本无错误地执行调整大小。

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

但是,我不确定如何在我的无服务器部署中捆绑它。如果我将 GraphicsMagick 安装到与 sudo yum --installroot=/var/task install GraphicsMagick 脚本相同的文件夹,并且 运行 我的脚本使用此 require 语句:

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

当我在 EC2 实例上 运行 我的脚本时,调整大小有效。但是,当我使用无服务器部署以及 Lambda 中的脚本 运行s 时,可执行文件似乎已损坏。 gm 在调用 gm(buffer).size(/*...*/).

时失败并出现以下错误

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

如何构建可以使用无服务器部署的 ImageMagick 或 GraphicsMagick 版本?

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

如果您可以将其放入 allowed size limits 并上传 zip 文件,您几乎可以使用任何您想要的 AWS Lambda 包。看看 AWS Lambda Deployment Limits 部分

此外,这里有一个如何打包依赖项的示例(针对 python 代码)

我启动了最新的 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 repo 代码,但针对无服务器进行了修改。

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;

serverless.yml

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

我使用工件并构建我自己的 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 layers。这种事情可能只需要做一次。

如果您想解决图像大小调整问题,您还可以查看 serverless sharp image library which uses Sharp,这是一个用于图像大小调整的高性能 Node.js 库,它比 [= 快大约 3 到 5 倍17=]。您没有提供足够的信息来说明它符合您的用例要求,但我只是想提一下,因为到目前为止,这个库已经为我节省了大量 AWS Lambda 成本。

顺便说一句:我与这个项目无关(但许可证是 MIT/Apache 许可证 2.0 无论如何)。

对于node.js,你可以使用node-lambda,它使用docker图像简化了打包:

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

-I 参数将启动一个 docker 图像并在您的项目中启动 npm i,因此它将根据正确的体系结构编译二进制文件 node_modules。

如果您在本地设备上安装 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 环境版本更改节点版本。

正如我所检查的,imageMagick 已经存在于 aws lambda 环境中。所以我们可以使用所有与imageMagick相关的库图形、图像。参考:https://serverless.com/blog/building-a-serverless-screenshot-service-with-lambda/

我为此苦苦挣扎了几天,最后自己完成了这个过程,它确实有效。

ImageMagick 不再与 Node.js 10.x 运行时捆绑在一起。有 3 个选项可以让 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" 太大,无法启用内联代码编辑。但是,您仍然可以调用您的函数。

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。但为了节省您的时间,这里有一个 zip 文件,您可以使用它来创建 Lambda 层。

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

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

然后您可以像这样创建 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 层的 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