AWS Lambda上でcanvasを使いたい【前編】の続きです。

色々と面倒なので全てrootユーザーで作業しています。ホームディレクトリは/rootです。適宜読み替えて下さい。

前回、AmazonLinux上のnode.jsでcanvasを動かしてみました。
今回はこれをAWS Lambda上で動かしてみます。まずは、Lambda上でのモジュールの使い方です。

モジュールをLambdaで使う場合zipファイルにまとめてからデプロイします。
その際に注意する点としてはzipファイルのルート直下に置かないと上手く動きません。

例えば下記の様な構造だったとします。

test
┣index.js
┗node_modules/

これをディレクトリごと圧縮してデプロイしても動きません。下記の様にtestディレクトリの中身だけをzipファイルにします。

cd test
zip -r test.zip index.js node_modules/

一つ簡単なサンプルを作ってみます。

mkdir underscore
cd underscore
npm install underscore

これでunderscoreのモジュールがインストールされました。このモジュールはPure JSなのでこのままlambda上で動くはずです。
そして、Lambda用の関数を作ります。

index.js
[javascript]
exports.handler = function(event, context) {
var _ = require(“underscore”);
var a = [];
console.log(_.isArray(a)); //true
};
[/javascript]

underscore.jsで変数が配列かどうかを調べるだけの簡単なものです。しかも配列を作って配列かどうか調べるアホみたいな関数ですw
これをAWSコンソールでLambda関数を作って、コピペして実行してもモジュールが読み込めないのでエラーになります。

zip -r test.zip index.js node_modules/

として、zipファイルにしてアップロードします。ファイルはAWSのコンソールから直接アップロードしてもいいのですが、EC2サーバー上から上げるときは面倒なのでAWS CLIを使って一度S3にあげるか、直接LambdaのAPIを使ってデプロイしてしまいます。サンプルコマンドのAWS CLIのバージョンは1.7.36です。lambdaのコマンドはバージョンによって結構変わっています。

testというprofileでAWSのキーとリージョンを設定してあります。このユーザーにはLambdaとS3の全権限を与えてあります。CLIのユーザー設定方法はこちらを参照。

S3に上げる場合。S3に上げた場合はAWSのコンソールから”Upload a .ZIP from S3″を選択してURLを貼り付けて下さい。S3のバケットがあるリージョンとLambdaを実行しているリージョンが違うと上手くいきません。

aws s3 cp test.zip s3://bucketname/test.zip –profile test

直接デプロイする場合。underscoreという名前で既に関数は作ってある前提です。

aws lambda update-function-code –function-name underscore –zip-file fileb:///root/underscore/test.zip –profile test

その後実行しますが、これはAWSのコンソールからした方が楽だし、わかりやすいですがコマンドだと下記の様になります。result.txtは出力が書き込まれるファイルです。

aws lambda invoke –function-name underscore result.txt –profile test

実行するとファイルの中身が true になっているはずです。

これでcanvasをLambdaで動かす準備が整いました。
まずは、Lambdaで動くかどうかわからないですが、前編で作ったサンプルスクリプトをローカルファイルでなく、S3に出力するよう変更してみます。

前編でのexampleディレクトリに移動して下記のファイルを作ります。その後zipにしてcanvasという名のlambdaを作ってアップロード、実行してみます。(AWSコンソールからでも、CLIでもどちらでもいいですが、関数を作るのはコンソール、アップロードはコマンドでやるのが楽なのでそうしています。)

index.js
[javascript]
exports.handler = function(event, context) {
var AWS = require(‘aws-sdk’);
var s3 = new AWS.S3({apiVersion: ‘2006-03-01’});
var Canvas = require(‘canvas’)
, Image = Canvas.Image
, canvas = new Canvas(200, 200)
, ctx = canvas.getContext(‘2d’);

ctx.font = ’30px Impact’;
ctx.rotate(.1);
ctx.fillText(“Awesome!”, 50, 100);

var te = ctx.measureText(‘Awesome!’);
ctx.strokeStyle = ‘rgba(0,0,0,0.5)’;
ctx.beginPath();
ctx.lineTo(50, 102);
ctx.lineTo(50 + te.width, 102);
ctx.stroke();

canvas.toBuffer(function (err, buf) {
if (err) throw err;
var params = {
Bucket: ‘bucketName’,
Key: ‘test.png’,
Body: buf ,
ContentType: ‘image/png’,
ACL: ‘public-read’

};
s3.putObject(params, function(err, data) {
if (err) {
context.done(null, err);
} else {
context.done(null, “done”);
}
});
});
};
[/javascript]

zip -r canvas.zip index.js node_modules/
aws lambda update-function-code –function-name canvas –zip-file fileb:///root/example/canvas.zip –profile test

さて、実行結果ですが、これで動くならこんな記事を書いていません。当然エラーがでます。

なので、動くようにしてみます。
まずインストールに使用するライブラリ等をコピーしてきてこれらのみを使ってモジュールをビルド出来るようにします。

cd ~
mkdir lib
cd lib
cp -r /usr/lib64/ ./
cp -r /usr/include/ ./
cd lib64/pkgconfig/
sed -i “s/\/usr/\/root\/lib/g” *
yum erase cairo

これで準備完了です。cairoのパッケージは削除して下さい。
このあとcanvasをインストールして、lambdaにアップロードします。

cd ~/example/
rm -rf node_modules/
PKG_CONFIG_PATH=~/lib/lib64/pkgconfig/ npm install canvas
zip -r canvas.zip index.js node_modules/
aws lambda update-function-code –function-name canvas –zip-file fileb:///root/example/canvas.zip –profile test

これで実行するとS3上にファイルが出来ているはずです。
タイムアウトになってしまうときはlambdaのタイムアウト時間を10秒程度にしてみて下さい。
nchartなんかのモジュールを使うとlambda上でcanvasを使ってグラフを書けたりします。

※作成から2年前(806日経過)の記事です。内容が古い可能性があります。
東京都東日本橋の株式会社プレスマンPRESSMAN*Tech