AWS Lambda のネイティブモジュール問題について

最近、AWS Lambdaを使う機会が増えてきてますが、その中でコード管理やユニットテスト、あるいはネイティブモジュール問題で手間取ったのでメモです。

ネイティブモジュール問題とは

Node.jsで開発する場合、npmで様々なライブラリをインストールすることになると思います。その際に、MacやWindowsでインストールしたnode_moduleをLambdaにアップロードすると、以下のようなエラーになることがあります。

This problem can often be fixed by running "npm rebuild" on the current system
sudo /usr/local/bin/node app.js
Error: Failed to load gRPC binary module because it was not installed for the current system
Expected directory: node-v57-linux-x64-glibc
Found: [node-v59-linux-x64-glibc]
This problem can often be fixed by running "npm rebuild" on the current system

何でこんなエラーが出るかというと、
https://qiita.com/kousaku-maron/items/057bcee356322524646b

Node.jsで利用できるモジュールの中にC/C++で書かれているものがあります。
そのようなモジュールはクロスプラットフォームのコマンドラインツールでビルドしてから利用できるようになっています。
そのようなモジュールはネイティブモジュールと呼ばれ、ビルドされたモジュールは違うOSでは動かないことが多々あります。
つまり、MacやWindowsPCのローカル環境でネイティブモジュールをインストールして、そのモジュールを利用したコードを書きLambdaで実行させようとするとOSの違いでうまく動かないことがあるということです。

ということらしい。
要はLambdaの実行環境と同じ環境でインストールしてあげる必要があるということです。

Lambdaと同じ環境を用意する

1.EC2を作成し、その中でインストール

一番手っ取り早く、簡単ではあるが若干面倒くさい方法です。最初はこれでやってましたが、イケてないです。
https://aws.amazon.com/jp/lambda/faqs/

AWS Lambda は Amazon EC2 と同じ技術を使用しており

なので、EC2上であればLambdaと同じ環境でライブラリをインストールすることができます。EC2にはnpmやNode.jsが入っていないので、以下のコマンドでインストールする必要があります。

curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash -
sudo yum -y install nodejs

この後、自分で入れたいライブラリをインストールし、できたnode_moduleフォルダをscpコマンドなどでローカルに落としてきて利用します(ただし、ローカルで実行しようとすると同じくネイティブモジュール問題で実行できないので注意です)。

2.ローカルにdockerでAmazon linuxを立てる

AWS公式のイメージで、amazonlinuxというdockerイメージがあるので、それを利用します。ちなみに、自分は仕事ではこの方法を使っています(環境を共有しやすいので)。

やり方は
https://blue21neo.blogspot.com/2017/01/docker-amazonlinux.html
など。

EC2と同様に、npmもNode.jsも入っていないので入れる必要があります。

3.Cloud9を使う

Cloud9とは、ブラウザ上で開発、実行までできるクラウドのIDEです。実際はEC2上で作業することになるので、Lambdaと同じ環境で作業することができます。

Macの場合、dockerが容易に利用できるので2の方法でいいかと思いますが、Windowsの場合はproじゃないとdocker for windowsが使えなかったりとか環境構築の時点で結構面倒だったりします(home→proにする場合は1万3000円くらいかかるし)。

自分の場合も家のPCがWindows10 homeだったので、proにあげる or Macを買う or docker toolbox を使う、などする必要がありました。が、正直面倒なので、Cloud9を使うことにしました。

Cloud9自体の始め方は以下を参照。
https://qiita.com/tu-kun/items/d7b4f1fa19cc93bc5b75

こちらもnpm、Node.jsが入っていないので入れる必要があります。

ちなみに、CLoud9はLambdaと連携していて、Lambdaからインポートしたり、新規作成、編集したLambda関数をLambdaにエクスポートしたりすることもできます。