
AWS Lambda(Node.js)にsharp(Native Module)をデプロイする方法
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
sharpはNode.js向けの画像変換ライブラリです。sharpは内部ではCで書かれたネイティブモジュールのlibvipsを利用しています。libvipsのインストールについては、メジャーなプラットフォーム(macOSやLinux x64,Linux ARM64, Windows)向けには予めビルドされたネイティブモジュール(バイナリ)が用意されており、sharpのインストール時にそれらが ./node_modules/sharp/vendor/ に展開される格好になっています。
ここで問題になってくるのが、macOSなどでインストールしたネイティブモジュールをそのままLambdaにデプロイしてしまうと、プラットフォームの違いによりlibvipsが動作しないことです。この問題についてはこれまでもいくつか類似記事が出ていますが、最新情報をまとめてみます。
パターン1: npm install
最もシンプルな方法で、sharpのドキュメントにも書かれています。
Installation - sharp - High performance Node.js image processing
rm -rf node_modules/sharp npm install --arch=x64 --platform=linux sharp
npm install コマンド実行時に --arch=x64 --platform=linux を指定することでLambdaのプラットフォームで利用可能なネイティブモジュールをインストールします。
どのプラットフォームでインストールされたかは、以下で確認ができます。
$ cat node_modules/sharp/vendor/platform.json "linux-x64"
ちなみに、 --arch=x64 --platform=linux のオプションは package.json の arch や platform を上書きするオプションです。その他 package.json の項目はすべて --key=value の形式で実行時に上書きすることができます。
$ npm help
Specify configs in the ini-formatted file:
    /Users/igarashi.ryosuke/.npmrc
or on the command line via: npm <command> --key value
Config info can be viewed via: npm help config
パターン2: LambdaのDockerイメージでインストールする
Lambdaと同じプラットフォームのイメージの中でインストールする方法です。これもsharpのドキュメントに書かれていますが、現在はamazon公式のLambdaのDockerイメージがありますのでそちらを使用しましょう。node12はまだ用意されていませんのでnode10.xで。
こちらの方法であれば yarn コマンドを使うこともできますのでここからは yarn を使っていきます。なお、 yarn.lock ファイルにはインストール時のプラットフォーム情報は記録されないのでローカルと共有して使うことができます。
rm -rf node_modules/sharp docker run -it --rm \ -v "$PWD":/var/task \ -w /var/task \ amazon/lambda-build-node10.x \ /bin/bash -c " \ npm install -g yarn && \ yarn install --production"
また、ローカル環境の ./node_modules は変更せずに、Dockerイメージの中でモジュールのインストールしてデプロイまでやってしまう場合は . をマウントしつつ ./node_modules だけをDocker Volumeにマウントしてあげれば良いです。
docker run -it --rm \ -v "$PWD":/var/task \ -v node_modules:/var/task/node_modules \ -w /var/task \ amazon/lambda-build-node10.x \ /bin/bash -c " \ npm install -g yarn && \ yarn install --production"
Docker Volumeは --rm オプションでは削除されないので、使い終わったら明示的に削除しましょう。
docker volume rm node_modules
関連記事
Node.jsのNative ModuleをAmazon Linux on Dockerでコンパイルする | Developers.IO
TypeScriptなら ./dist をLambdaのルートに指定して、モジュールを ./dist/node_modules に配置してデプロイしてもよさそうです。
CircleCI と GitHub で AWS SAM のサーバーレスアプリを自動デプロイしてみた (開発環境 & 本番環境) | Developers.IO
CI環境ならLambdaのDockerイメージを使ってインストールできるので良いですね。












