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

Posted

技术标签:

【中文标题】如何在 AWS Lambda 上安装 GraphicsMagick 或 ImageMagick?【英文标题】:How can I install GraphicsMagick or ImageMagick on AWS Lambda? 【发布时间】:2017-11-27 11:39:17 【问题描述】:

我正在使用适用于 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 实例。 我安装了可从yum 获得的(旧)6.x 版本的 ImageMagick。当我在 EC2 实例上使用该安装运行我的脚本时,它会重现我在 Lambda 上运行代码时看到的故障,确认是这个版本的 IM 导致了故障。

如果我使用sudo yum install GraphicsMagick 安装 GraphicsMagick。这允许我的脚本执行调整大小而不会出错。

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

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

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

当我在 EC2 实例上运行我的脚本时,调整大小会起作用。但是当我使用无服务器部署并且脚本在 Lambda 中运行时,可执行文件似乎已损坏。 gm 在调用 gm(buffer).size(/*...*/) 时失败并出现以下错误。

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

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

【问题讨论】:

【参考方案1】:

我启动了最新的 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;

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。这种事情可能只需要做一次。

【讨论】:

更改为 ./configure --prefix=/var/task/graphicsmagick --enable-shared=no --enable-static=yes 我正在为依赖库苦苦挣扎...例如,当我在 lambda 上运行 gm 时找不到 libjpeg.so.62 除了列出的软件包之外,我还必须安装 targzipmake。代替 scp 的另一个选项是(在主机上)运行 docker cp [container id]:/root/graphicsmagick.tgz ./ 你在哪里运行这些命令。我创建了一个 lambda 函数,它给了我同样的错误并且在本地运行良好。您能否指定运行命令的方式和位置? 我的简单 lambda 函数的 serverless.yml 在哪里?【参考方案2】:

我为此苦苦挣扎了几天,最终自己经历了这个过程,它确实有效。

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

【讨论】:

我刚刚上传了图层(第 2 步),它立即开始工作。非常感谢!伟大的工作【参考方案3】:

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

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

【讨论】:

在切换之前记住夏普的限制:sharp.pixelplumbing.com/en/stable/api-input/#limitinputpixels 如果你想处理大图像,那可能是个问题。 夏普也有同样的问题。你需要有 docker 来构建它。【参考方案4】:

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

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

另外,这里有一个如何打包依赖的例子(对于python代码)https://***.com/a/36093281/358013

【讨论】:

我已经在包中安装了 imagemagick,我可以在 node_modules 文件夹中看到它。但它仍然给出了同样的错误。在本地,我已经在 ubuntu 上安装了 imageMagick,它运行良好。不知道怎么在lambda环境下安装。 @OsamaKhalid 您没有安装在 lambda 环境中。在这种情况下,您将打包所有依赖项,即 imageMagick。参考这个例如***.com/questions/36054976/pandas-aws-lambda/…【参考方案5】:

对于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?【参考方案6】:

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

【讨论】:

【参考方案7】:

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

【讨论】:

以上是关于如何在 AWS Lambda 上安装 GraphicsMagick 或 ImageMagick?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用AWS Lambda函数在本地系统上执行文件

你如何在Typescript中优雅地导入AWS-Lambda?

如何使用 AWS Lambda 在 AWS EMR 上运行 PySpark

AWS Lambda 自动化和 PowerShell

如何从AWS Lambda检索数据并将其显示在AWS S3托管的静态网站上?

如何使用 NodeJS 在 AWS Lambda 上运行 PhantomJS