Help us understand the problem. What is going on with this article?

Lambda Node.js8.10から10.xへの バージョンアップに伴うImageMagickの対応

はじめに

今回、LambdaランタイムNode.js8.10のサポート終了に伴い、Node.js10.xへアップデートを行いました。
結構詰まった部分などが合ったので、その備忘録として残します。

LambdaランタイムNode.js8.10のサポート終了について

以下、AWS公式より
スクリーンショット 2020-01-24 14.17.37.png
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/runtime-support-policy.html

2020/2/3を持ってLambdaのランタイムNode.js8.10の更新が終了します。
これに伴い、Node.js8.10で実装しているLambdaのランタイムを10.xにバージョンアップをしました。

Lambdaのランタイム変更による変更内容

大きな変更は、コンテナ内で起動するEC2のOSがAmazon LinuxからAmazon Linux2へ変わることです。
これにより、もともとデフォルトでOSにインストールされていた、graphicsmagickimagemagickがAmazon Linux2ではインストールされていないという状態になります。

こちらが参考記事です
https://note.com/mohya/n/n48692d8e4a57#jgl1s
つまり、Node.js10以上で、imagemagickなどを使いたい場合は、インストールしなければけません。

本記事では、この点についての対応方法を紹介します。

手順

  1. 単純にランタイムを変更する
  2. Lambdaを実行させ、エラー内容を確認する
  3. graphicsmagickとimagemagickのレイヤーを追加する
  4. Lambdaを実行させ、成功を確認する

1. 単純にランタイムを変更する

まず、状況確認をするために単純にランタイムを変更します。
スクリーンショット 2020-01-24 15.36.06.png

2. Lambdaを実行させ、エラー内容を確認する

以下のようなエラーが出ました。

2020-01-24T02:40:09.509Z    c28c7e8b-b775-48ae-ac36-aec733c9b025    ERROR   Invoke Error    
{
    "errorType": "Error",
    "errorMessage": "Could not execute GraphicsMagick/ImageMagick: identify \"-ping\" \"-format\" \"%wx%h\" \"-\" this most likely means the gm/convert binaries can't be found",
    "stack": [
        "Error: Could not execute GraphicsMagick/ImageMagick: identify \"-ping\" \"-format\" \"%wx%h\" \"-\" this most likely means the gm/convert binaries can't be found",
        "    at ChildProcess.<anonymous> (/opt/nodejs/node_modules/gm/lib/command.js:232:12)",
        "    at ChildProcess.emit (events.js:198:13)",
        "    at ChildProcess.EventEmitter.emit (domain.js:448:20)",
        "    at Process.ChildProcess._handle.onexit (internal/child_process.js:246:12)",
        "    at onErrorNT (internal/child_process.js:415:16)",
        "    at process._tickCallback (internal/process/next_tick.js:63:19)"
    ]
}

ImageMagickが見つからず、実行できないと言われてしまっています。

3. graphicsmagickとimagemagickのレイヤーを追加する

ここがメインです。
Amazon Linux2ではImageMagickが存在しないので、インストールする必要があります。
こちらのissueが大変参考になりました。
https://github.com/ysugimoto/aws-lambda-image/issues/191

Imagemagickレイヤーの設置

サーバーレスレポジトリにて提供されているので、こちらから作成します。
https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:145266761615:applications~image-magick-lambda-layer

Gaphicsmagickレイヤーの設置

こちらは、誰か知らない人が作ってくれているので、使っちゃいます。
https://github.com/rpidanny/gm-lambda-layer
こちらは、Dockerになっていて、あれ???と思いましたが
LayerもそれぞれDockerを起動してくれ、起動時にDockerfileに記載してあるこの辺りでインストールしてくれます。

RUN curl https://versaweb.dl.sourceforge.net/project/graphicsmagick/graphicsmagick/${GM_VERSION}/GraphicsMagick-${GM_VERSION}.tar.xz | tar -xJ && \
cd GraphicsMagick-${GM_VERSION} && \
./configure --prefix=/opt --enable-shared=no --enable-static=yes --with-gs-font-dir=/opt/share/fonts/default/Type1 && \
make && \
make install

このレイヤーをLambdaに登録しておけば、いいらしいですね。便利です。

レイヤーの適応

今回はServerless Frameworkを使用しているため、ymlで記載します。

functions:
  storePhotoData:
    handler: storePhotoData.handler
    layers:
      - arn:aws:lambda:ap-northeast-1:579663348364:layer:image-magick:1
      - arn:aws:lambda:ap-northeast-1:175033217214:layer:graphicsmagick:2
      - { Ref: MyLayerLambdaLayer }
    tracing: Active
    description: create storePhotoData
    memorySize: 2048
    timeout: 10
    role: storePhotoDataLambdaFunctionRole

レイヤーには実行順序という概念もあるため、レイヤーの順番も気をつけなければなりません。
MyLayerLambdaLayer はカスタマイズして作ったレイヤーで、graphicsmagickとimagemagickがないと実行できないので、念の為後ろに持ってきました。
(あんまり意味ないかも...)

4. Lambdaを実行させ、成功を確認する

ログが出せないのが申し訳ないですが、これで成功しました!!

Node.js 12.xの対応

この時どうせならと思ってランタイムをNode.js12.xにしてみたのですが、一応動きました。w
少しだけ気になる点もありましたが、恐らく大丈夫かなと思います。
一気に12へあげたい方はやってみてください。

追記

先日、AWSの中の人のサーバーレスのLTを聴講しました。
そこで言われたのは、LambdaはNode.jsでわざわざやるメリットがあまりない とのことでした。(あくまで個人的な意見として)
そもそも今回のようにサポート終了になった場合に、ランタイム変更をしなければならないし、Node.js自体がサポートの動きが激しいので、それに伴って対応しなければいけないことが多いようです。
また、Node.jsの特性上、Lambdaのようにファンクション一つだけでの処理の場合、非同期により得られるメリットもあまりないよね、みたいなことをおっしゃっていました。
(確かに、現在使っているLambdaの場合waterfallを用いて無理やり同期処理させています)

弊社アプリケーションの場合、Lambdα@Edgeを検討していた背景からNode.jsを採択しましたが、今となってはEdgeも使わなそうなので、PythonやGoに切り替えるという選択肢もあるかなと思います。

今後、言語別の速度比較なども含めて検証したいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした