AWS Lambda(Node.js)にsharp(Native Module)をデプロイする方法
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イメージを使ってインストールできるので良いですね。