Lambda Layerを使ってSharpを使用した画像リサイズ機能を作る方法を学ぼう
Lambda Layerは、Lambda機能の世界で真の宝石です。ライブラリやその他の依存関係をパッケージングする便利な方法を提供し、Lambda関数で使用することができます。GitHubで50,000以上のダウンロードと5,500のスターを持つオープンソースプロジェクトのWebinyは、Lambda Layerを使用しています。これによって我々のLambda機能のサイズを12MB削減し、すべてのWebinyデプロイメントで画像処理ライブラリsharpを共有することができます。
この記事を読み終える頃には、Lambda Layerの作成と使用方法を学べるでしょう。例として、SharpライブラリLayerを作成し、サムネイル画像を作成するためにLambda関数でそれを使用します。
このチュートリアルでは、sharp
ライブラリを使用してサムネイル画像を作成するLambda関数を作成します。このライブラリは、Lambda Layerを使用してLambda関数にパッケージ化されます。
ワークフローはこのようになります。S3バケット(ソースバケット)に画像ファイルがアップロードされるたびに、Lambda関数が呼び出されます。ソースS3バケットから画像オブジェクトを読み取り、サムネイル画像を作成し、ターゲットS3バケットに保存します。
前提条件
- AWSアカウント - 様々なAWSサービスを使用するには、AWSアカウントが必要です。AWSアカウントを作成するにはこのリンクに従ってください。
- AWSコマンドライン - Lambda関数とLambda Layerを作成するために、AWSコマンドラインを使用します。AWS CLIのインストールガイドはこちらです。
ステップ1 - 2つのS3バケットを作成する
まず、ソースとターゲットの2つのバケットを作成しましょう。前述したように、ソースバケットに画像ファイルがアップロードされるたびに、Lambda関数は対応するサムネイル画像を作成し、ターゲットS3バケットに保存します。
S3バケットを作成するための手順は以下の通りです。
1.) Amazon S3コンソールを開きます。
2.) 2つのS3バケットを作成する - ソースとターゲット。
ターゲットバケット名は、source-bucket-name
と後ろに-resized
を接尾辞として付ける必要があります。例えば、ソースバケットがmybucket
という名前なら、ターゲットバケットはmybucket-resized
と命名します。この命名規則に従ってください。なぜなら、この命名ロジックをLambda関数で使用するからです。
ステップ2 - IAMポリシーを作成する
次に、Lambda関数のための権限を指定するIAMポリシーを作成しましょう。Lambda関数は、次の操作の権限を持っている必要があります:
- ソースS3バケットからオブジェクトを取得する。
- ターゲットS3バケットにリサイズされたオブジェクトを配置する。
- Amazon CloudWatch Logsにログを書き込む。
IAMポリシーを作成するには
1.) IAMコンソールのポリシーのページを開きます。
2.) ポリシーの作成を選びます。
3.) JSONタブを選び、次のポリシーを貼り付けます。事前に作成したソースバケットの名前でmybucket
を置き換えてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:PutLogEvents",
"logs:CreateLogGroup",
"logs:CreateLogStream"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::mybucket/*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::mybucket-resized/*"
}
]
}
4.) Next: Tagsを選びます。
5.) Next: Reviewを選びます。
6.) Review policyのもとで、NameでAWSLambdaS3Policy
を入力します。
7.) Create policyを選びます。
ステップ3 - 実行ロールを作成する
AWSリソースにアクセスする権限をLambda関数に与える実行ロールを作成します。
実行ロールを作成するには
1.) IAMコンソールのロールのページを開きます。
2.) ロールの作成を選びます。
3.) 次のプロパティを持つロールを作成します:
- 信頼されたエンティティタイプ - AWSサービス(EC2、LambdaなどのAWSサービスがこのアカウントでアクションを実行できるようにします。)
- ユースケース - Lambda(Lambda関数がAWSサービスを代わって呼び出せるようにします。)
- パーミッションポリシー – AWSLambdaS3Policy
- ロール名 – lambda-s3-role
ステップ4 - Sharp Lambda Layerを作成する
このチュートリアルの特別な部分に来ました。このセクションでsharp Lambda Layerを作成します。
このチュートリアルのこの部分は、あなたのマシンで実行されます。npm
がインストールされていることを確認してください(sharp
パッケージをインストールするためにnpm
が必要です)。
1.) nodejs
という名前のディレクトリを作成します。
2.) 次のコマンドを実行してnodejs
ディレクトリにsharp
依存関係をインストールします:
npm install
SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install --arch=x64 --platform=linux sharp
このステップ後、以下のディレクトリ構造が得られます:
nodejs
|- node_modules
|- package-lock.json
3.) nodejs
ディレクトリの.zip
ファイルアーカイブを作成します。
zip -r nodejs.zip nodejs
4.) レイヤーを公開しましょう。レイヤーを作成して公開するために、次のコマンドを実行します:
aws lambda publish-layer-version --layer-name sharp --description "Sharp dependency for image transformation" --zip-file fileb://nodejs.zip --compatible-runtimes "nodejs14.x" --region "us-east-1" --output "json"
コマンドを正常に実行した後、このような出力が表示されます。
LayerVersionArn
を注目してください。Lambda関数の作成時に使用します。
{
"LayerArn": "arn:aws:lambda:us-east-1:400803493251:layer:sharp",
"LayerVersionArn": "arn:aws:lambda:us-east-1:400803493251:layer:sharp:1",
...
}
ステップ5 - Lambda関数を作成する
sharp
Lambda Layerを使用するLambda関数を作成しましょう。以前に話したように、このLambda関数は、オブジェクトがソースバケットに作成されるときに呼び出されます。それから、それぞれのサムネイル画像を作成し、ターゲットバケットに保存します。以下のコード例は、ステップ1で述べたS3バケット名の規則に従っていることを前提としています。
ステップ5.1 関数コードを作成する
index.js
という名前のファイルに次のコード例をコピーします。
// 依存関係
const AWS = require('aws-sdk');
const util = require('util');
const sharp = require('sharp');
// S3クライアントへの参照を取得
const s3 = new AWS.S3();
exports.handler = async (event, context, callback) => {
// イベントパラメータからオプションを読み取ります。
console.log("Reading options from event:\n", util.inspect(event, {depth: 5}));
const srcBucket = event.Records[0].s3.bucket.name;
// オブジェクトキーはスペースやユニコード非ASCII文字を含むことがあります。
const srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
const dstBucket = srcBucket + "-resized";
const dstKey = "resized-" + srcKey;
// ...(中略)...
try {
var buffer = await sharp(origimage.Body).resize(width).toBuffer();
// ...(中略)...
console.log('Successfully resized ' + srcBucket + '/' + srcKey +
' and uploaded to ' + dstBucket + '/' + dstKey);
} catch (error) {
console.log(error);
return;
}
};
ステップ5.2 配置パッケージを作成する
配置パッケージは、Lambda関数コードとその依存関係を含む.zipファイルアーカイブです。
1.) Linux環境でコマンドライン端末またはシェルを開きます。
2.) lambda-s3
という名前のディレクトリにindex.js
関数コードを保存します。
このステップ後、以下のディレクトリ構造が得られます:
lambda-s3
|- index.js
3.) zipコマンドに-r(再帰的)オプションを設定して、関数コードとその依存関係を含む配置パッケージを作成します。
このコマンドをlambda-s3
ディレクトリで実行します。
zip -r function.zip .
ステップ5.3 Lambda関数を作成する
AWS CLIコマンド(aws lambda create-function
)を使用してLambda関数を作成します。
以下のコマンドにあるロールパラメータ123456789012
をあなたのAWSアカウントIDに、ステップ4で得たレイヤーARN(LayerVersionArn
)と置き換えてください。
aws lambda create-function --function-name CreateThumbnail \
--zip-file fileb://function.zip --handler index.handler --runtime nodejs14.x \
--timeout 30 --memory-size 1024 \
--role arn:aws:iam::123456789012:role/lambda-s3-role \
--region "us-east-1" \
--layers "arn:aws:lambda:us-east-1:400803493251:layer:sharp:1"
上記コマンドの実行に成功すると、以下のような出力が表示されます:
{
"FunctionName": "CreateThumbnail",
"FunctionArn": "arn:aws:lambda:us-east-1:400803493251:function:CreateThumbnail",
...
}
ステップ6 - Amazon S3トリガーを設定する
これまでに作成したすべての構成要素があります。最後の部品を加え、Amazon S3トリガーを設定してLambda関数を呼び出すようにしましょう。
S3ファイルがアップロードされると、サムネイルを作成し、ターゲットS3バケットにアップロードするLambda関数がトリガーされるはずです。
Amazon S3トリガーを作成するには
1.) AWSコンソールのLambdaページを開きます。
2.) CreateThumbnail
関数を開きます。
3.) Function overviewセクションでAdd triggerを選択します。
4.) 以下のプロパティでトリガーを作成します:
- トリガーを選択 - S3
- バケット - mybucket(あなたのソースバケット名)
- イベントタイプ - PUT
ステップ7 - すべての設定が完了したので、テストしましょう!
素晴らしいですね。サムネイル画像を作成するsharp Layerを使用するLambda関数の準備が整いました。ソースS3バケットに画像(jpgまたはpng)をアップロードしてください。アップロードが完了すると、ターゲットS3バケットで画像のサムネイルバージョンを見ることができるはずです。
Lambda Layerは、Lambda関数と共に使用するライブラリやその他の依存関係をパッケージ化する非常に効率的で便利な方法です。デプロイアーカイブのサイズを小さくし、デプロイを早める大きなメリットがあります。Layersはコードの共有と責任の分離を可能にし、保守可能なLambda関数を作ります。
Lambdaに関連するベストプラクティスやコード例についてさらに探求して学びたい場合は、Webinyのコードリポジトリをチェックしてください。WebinyはオープンソースのエンタープライズグレードのサーバーレスCMSです。
このチュートリアルやフィ
こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/webiny/learn-how-to-use-lambda-layers-by-building-an-image-resize-function-using-sharp-bj4