AWS Lambda
開発者ガイド

チュートリアル: Amazon S3 で AWS Lambda を使用する

バケットにアップロードされる各画像ファイルのサムネイルを作成するとします。オブジェクトの作成時に Amazon S3 が呼び出すことができる Lambda 関数 (CreateThumbnail) を作成できます。その後、Lambda 関数はソースバケットから画像オブジェクトを読み取り、ターゲットバケットにサムネイル画像を作成できます。

このチュートリアルを完了すると、アカウントで以下の Amazon S3、Lambda、および IAM リソースが作成されます。

Lambda リソース

  • Lambda 関数。

  • Amazon S3 に Lambda 関数を呼び出すアクセス許可を付与する Lambda 関数に関連付けられたアクセスポリシーです。

IAM リソース

  • このロールに関連付けられたアクセス権限ポリシーを使用して Lambda 関数に必要なアクセス許可を付与する実行ロールです。

Amazon S3 リソース

  • Lambda 関数を呼び出す通知設定を持つソースバケット。

  • 関数がサイズ変更された画像を保存するターゲットバケットです。

前提条件

実行ロールを作成する

AWS リソースにアクセスするためのアクセス権限を関数に付与する実行ロールを作成します。

実行ロールを作成するには

  1. IAM コンソールのロールページを開きます。

  2. [ロールの作成] を選択します。

  3. 次のプロパティでロールを作成します。

    • [信頼されたエンティティ] – [AWS Lambda]。

    • [Permissions (アクセス許可)] – [AWSLambdaExecute]。

    • ロール名lambda-s3-role

AWSLambdaExecute ポリシーには、Amazon S3 でオブジェクトを管理してログを CloudWatch Logs に書き込むために関数が必要とするアクセス許可があります。

バケットを作成しサンプルオブジェクトをアップロードする

バケットを作成し、オブジェクトをアップロードするための手順を行います。

  1. Amazon S3 コンソールを開きます。

  2. バケットを 2 つ作成します。ターゲットバケット名は、source とその後に resized を連結したものになる必要があります。ここで、source は、ソースに使用するバケットの名前です。たとえば、mybucketmybucketresized です。

  3. ソースバケットで、.jpg オブジェクトの HappyFace.jpg をアップロードします。

    Lambda 関数を手動で呼び出すときは、Amazon S3 に接続する前に、ソースバケットと新しく作成されるオブジェクト (HappyFace.jpg) を指定するサンプルイベントデータをその関数に渡します。そのため、最初にこのサンプルオブジェクトを作成する必要があります。

関数を作成する

以下のコード例では、Amazon S3 イベント入力を受け取り、含まれるメッセージを処理します。ソースバケットのイメージのサイズを変更し、ターゲットバケットに出力を保存します。

注記

他の言語によるサンプルコードについては、「サンプル Amazon Simple Storage Service 関数コード」を参照してください。

例 index.js

// dependencies var async = require('async'); var AWS = require('aws-sdk'); var gm = require('gm') .subClass({ imageMagick: true }); // Enable ImageMagick integration. var util = require('util'); // constants var MAX_WIDTH = 100; var MAX_HEIGHT = 100; // get reference to S3 client var s3 = new AWS.S3(); exports.handler = function(event, context, callback) { // Read options from the event. console.log("Reading options from event:\n", util.inspect(event, {depth: 5})); var srcBucket = event.Records[0].s3.bucket.name; // Object key may have spaces or unicode non-ASCII characters. var srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " ")); var dstBucket = srcBucket + "resized"; var dstKey = "resized-" + srcKey; // Sanity check: validate that source and destination are different buckets. if (srcBucket == dstBucket) { callback("Source and destination buckets are the same."); return; } // Infer the image type. var typeMatch = srcKey.match(/\.([^.]*)$/); if (!typeMatch) { callback("Could not determine the image type."); return; } var imageType = typeMatch[1]; if (imageType != "jpg" && imageType != "png") { callback('Unsupported image type: ${imageType}'); return; } // Download the image from S3, transform, and upload to a different S3 bucket. async.waterfall([ function download(next) { // Download the image from S3 into a buffer. s3.getObject({ Bucket: srcBucket, Key: srcKey }, next); }, function transform(response, next) { gm(response.Body).size(function(err, size) { // Infer the scaling factor to avoid stretching the image unnaturally. var scalingFactor = Math.min( MAX_WIDTH / size.width, MAX_HEIGHT / size.height ); var width = scalingFactor * size.width; var height = scalingFactor * size.height; // Transform the image buffer in memory. this.resize(width, height) .toBuffer(imageType, function(err, buffer) { if (err) { next(err); } else { next(null, response.ContentType, buffer); } }); }); }, function upload(contentType, data, next) { // Stream the transformed image to a different S3 bucket. s3.putObject({ Bucket: dstBucket, Key: dstKey, Body: data, ContentType: contentType }, next); } ], function (err) { if (err) { console.error( 'Unable to resize ' + srcBucket + '/' + srcKey + ' and upload to ' + dstBucket + '/' + dstKey + ' due to an error: ' + err ); } else { console.log( 'Successfully resized ' + srcBucket + '/' + srcKey + ' and uploaded to ' + dstBucket + '/' + dstKey ); } callback(null, "message"); } ); };

デプロイパッケージは、Lambda 関数のコードと依存関係を含む .zip ファイルです。

デプロイパッケージを作成するには

  1. フォルダ (examplefolder) を作成してから、サブフォルダ (node_modules) を作成します。

  2. Node.js プラットフォームをインストールします。詳細については、Node.js のウェブサイトを参照してください。

  3. 依存関係をインストールします。コード例では、以下のライブラリを使用します。

    • Node.js 内の AWS SDK for JavaScript

    • gm(node.js の GraphicsMagick)

    • 非同期ユーティリティモジュール

    AWS Lambda ランタイムには Node.js に AWS SDK for JavaScript がすでにあるため、他のライブラリをインストールする必要があります。コマンドプロンプトを開き、examplefolder に移動し、npm コマンドを使用して Node.js の一部であるライブラリをインストールします。

    npm install async gm
  4. index.js という名前のファイルにサンプルコードを保存します。

  5. 前述のコードを確認し、以下の点に注意します。

    • 関数は、パラメータとして受信するイベントデータから、ソースバケット名とオブジェクトのキー名を知ることができます。オブジェクトが .jpg の場合、コードではサムネイルが作成され、ターゲットバケットに保存されます。

    • コードでは、ターゲットバケットが存在し、ソースバケット名の後に文字列 resized を連結したものがそのバケット名になっているとします。たとえば、イベントデータで特定されたソースバケットが examplebucket の場合、コードでは examplebucketresized 宛先バケットがあると想定されます。

    • 作成されるサムネイルについて、コードでは、文字列 resized- の後にソースオブジェクトキー名を連結したものをそのキー名として生成します。たとえば、ソースオブジェクトキーが sample.jpg の場合、コードではキー resized-sample.jpg があるサムネイルオブジェクトが作成されます。

  6. ファイルを index.js として examplefolder に保存します。この手順を完了すると、以下のようなフォルダー構造になります。

    index.js /node_modules/gm /node_modules/async
  7. index.js ファイルと node_modules フォルダを CreateThumbnail.zip という名前で ZIP 圧縮します。

関数を作成するには

  • create-function コマンドを使用して Lambda 関数を作成します。

    $ aws lambda create-function --function-name CreateThumbnail \ --zip-file fileb://function.zip --handler index.handler --runtime nodejs8.10 \ --role role-arn \ --timeout 10 --memory-size 1024

前述のコマンドは、関数の設定として 10 秒のタイムアウト値を指定します。アップロードするオブジェクトのサイズに応じて、次の AWS CLI コマンドを使用してタイムアウトの値を増やす必要が生じる場合があります。

$ aws lambda update-function-configuration --function-name CreateThumbnail --timeout 30

Lambda 関数をテストする

このステップでは、サンプル Amazon S3 イベントデータを使用して、手動で Lambda 関数を呼び出します。

Lambda 関数をテストするには

  1. 以下の Amazon S3 サンプルイベントデータを inputFile.txt としてファイルに保存します。JSON を実際の sourcebucket 名と .jpg オブジェクトキーで更新する必要があります。

    { "Records":[ { "eventVersion":"2.0", "eventSource":"aws:s3", "awsRegion":"us-west-2", "eventTime":"1970-01-01T00:00:00.000Z", "eventName":"ObjectCreated:Put", "userIdentity":{ "principalId":"AIDAJDPLRKLG7UEXAMPLE" }, "requestParameters":{ "sourceIPAddress":"127.0.0.1" }, "responseElements":{ "x-amz-request-id":"C3D13FE58DE4C810", "x-amz-id-2":"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD" }, "s3":{ "s3SchemaVersion":"1.0", "configurationId":"testConfigRule", "bucket":{ "name":"sourcebucket", "ownerIdentity":{ "principalId":"A3NL1KOZZKExample" }, "arn":"arn:aws:s3:::sourcebucket" }, "object":{ "key":"HappyFace.jpg", "size":1024, "eTag":"d41d8cd98f00b204e9800998ecf8427e", "versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko" } } } ] }
  2. 次の Lambda CLI invoke コマンドを実行して関数を呼び出します。コマンドは非同期実行をリクエストします。オプションで、invocation-type パラメータ値として RequestResponse を指定することで、このコマンドを同期的に呼び出すこともできます。

    $ aws lambda invoke --function-name CreateThumbnail --invocation-type Event \ --payload file://inputfile.txt outputfile.txt
  3. ターゲットバケットでサムネイルが作成されたことを確認します。

Amazon S3 の設定とイベントの発行

このステップでは、残りの設定を追加し、Amazon S3 がオブジェクト作成イベントを AWS Lambda に発行し、Lambda 関数を呼び出せるようにします。このステップでは、以下の作業を行います。

  • Lambda 関数のアクセスポリシーに、この関数の呼び出しを Amazon S3 に許可するアクセス権限を追加します。

  • 通知設定をソースバケットに追加します。通知設定で、以下の項目を指定します。

    • Amazon S3 がイベントを発行するイベントタイプ。このチュートリアルでは、s3:ObjectCreated:* イベントタイプを指定し、オブジェクトが作成されたときに Amazon S3 がイベントを発行するようにします。

    • 呼び出す Lambda 関数。

関数ポリシーにアクセス許可を追加するには

  1. 以下の Lambda CLI add-permission コマンドを実行して、Amazon S3 サービスプリンシパル(s3.amazonaws.com)に lambda:InvokeFunction アクションを実行するためのアクセス権限を付与します。次の条件を満たす場合にのみ関数を呼び出すアクセス権限が Amazon S3 に付与されることに注意してください。

    • オブジェクト作成イベントが、特定のバケットで検出されます。

    • 各バケットは、特定の AWS アカウントによって所有されます。バケット所有者がバケットを削除した場合、他の一部の AWS アカウントは同じ名前でバケットを作成できます。この状態により、特定の AWS アカウントのみが Lambda 関数を実行できるようになります。

    $ aws lambda add-permission --function-name CreateThumbnail --principal s3.amazonaws.com \ --statement-id some-unique-id --action "lambda:InvokeFunction" \ --source-arn arn:aws:s3:::sourcebucket \ --source-account bucket-owner-account-id
  2. AWS CLI get-policy コマンドを呼び出すことで、関数のアクセスポリシーを確認します。

    $ aws lambda get-policy --function-name function-name

オブジェクト作成イベントを Lambda に発行するよう Amazon S3 にリクエストするため、ソースバケットで通知設定を追加します。

通知を設定するには

  1. Amazon S3 コンソールを開きます。

  2. ソースバケットを選択します。

  3. [Properties (プロパティ)] を選択します。

  4. [Events (イベント)] で、以下の設定を使用して通知を設定します。

    • Name (名前)lambda-trigger

    • [Events (イベント)] – ObjectCreate (All)

    • [Send to (送信先)] – Lambda function

    • [Lambda] – CreateThumbnail

イベント設定の詳細については、『Amazon Simple Storage Service コンソールユーザーガイド』の「イベント通知の有効化」を参照してください。

セットアップをテストする

これで、次のようにセットアップをテストできます。

  1. Amazon S3 コンソールを使って、.jpg または .png オブジェクトをソースバケットにアップロードします。

  2. CreateThumbnail 関数を使用してサムネイルがターゲットバケットに作成されたことを確認します。

  3. CloudWatch コンソールでログを表示します。