メニュー
AWS Lambda
開発者ガイド

ステップ 2.1: デプロイパッケージを作成する

[Filter View] リストから、Lambda 関数で使用する言語を選択します。該当するセクションに、デプロイパッケージを作成するためのコードと所定の手順が表示されます。

Node.js

デプロイパッケージは、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 の一部であるライブラリをインストールします。

    Copy
    npm install async gm
  4. テキストエディターを開き、次のコードをコピーします。

    Copy
    // 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"); } ); };

    注記

    コードサンプルは、Node.js ランタイム v6.10 または v4.3 に準拠しています。詳細については、「プログラミングモデル (Node.js)」を参照してください。

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

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

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

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

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

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

    これが Lambda 関数デプロイパッケージです。

次のステップ

ステップ 2.2: 実行ロール (IAM ロール) を作成する

Java

以下に示すのは、受信する Amazon S3 イベントを読み取り、サムネイルを作成する Java コードの例です。この例では、aws-lambda-java-core ライブラリに用意された RequestHandler インターフェイスを実装しています。したがって、Lambda 関数を作成するときは、クラスをハンドラ (example.S3EventProcessorCreateThumbnail) として指定します。インターフェイスを使用したハンドラの提供の詳細については、「ハンドラ作成用に事前定義されているインターフェイスの利用 (Java)」を参照してください。

ハンドラが入力型として使用する S3Event 型は、受信する Amazon S3 イベントから簡単に情報を読み取るためのメソッドを提供する、aws-lambda-java-events ライブラリの定義済みクラスの 1 つです。このハンドラは出力として文字列を返します。

Copy
package example; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.S3Event; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.event.S3EventNotification.S3EventNotificationRecord; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.S3Object; public class S3EventProcessorCreateThumbnail implements RequestHandler<S3Event, String> { private static final float MAX_WIDTH = 100; private static final float MAX_HEIGHT = 100; private final String JPG_TYPE = (String) "jpg"; private final String JPG_MIME = (String) "image/jpeg"; private final String PNG_TYPE = (String) "png"; private final String PNG_MIME = (String) "image/png"; public String handleRequest(S3Event s3event, Context context) { try { S3EventNotificationRecord record = s3event.getRecords().get(0); String srcBucket = record.getS3().getBucket().getName(); // Object key may have spaces or unicode non-ASCII characters. String srcKey = record.getS3().getObject().getKey() .replace('+', ' '); srcKey = URLDecoder.decode(srcKey, "UTF-8"); String dstBucket = srcBucket + "resized"; String dstKey = "resized-" + srcKey; // Sanity check: validate that source and destination are different // buckets. if (srcBucket.equals(dstBucket)) { System.out .println("Destination bucket must not match source bucket."); return ""; } // Infer the image type. Matcher matcher = Pattern.compile(".*\\.([^\\.]*)").matcher(srcKey); if (!matcher.matches()) { System.out.println("Unable to infer image type for key " + srcKey); return ""; } String imageType = matcher.group(1); if (!(JPG_TYPE.equals(imageType)) && !(PNG_TYPE.equals(imageType))) { System.out.println("Skipping non-image " + srcKey); return ""; } // Download the image from S3 into a stream AmazonS3 s3Client = new AmazonS3Client(); S3Object s3Object = s3Client.getObject(new GetObjectRequest( srcBucket, srcKey)); InputStream objectData = s3Object.getObjectContent(); // Read the source image BufferedImage srcImage = ImageIO.read(objectData); int srcHeight = srcImage.getHeight(); int srcWidth = srcImage.getWidth(); // Infer the scaling factor to avoid stretching the image // unnaturally float scalingFactor = Math.min(MAX_WIDTH / srcWidth, MAX_HEIGHT / srcHeight); int width = (int) (scalingFactor * srcWidth); int height = (int) (scalingFactor * srcHeight); BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = resizedImage.createGraphics(); // Fill with white before applying semi-transparent (alpha) images g.setPaint(Color.white); g.fillRect(0, 0, width, height); // Simple bilinear resize // If you want higher quality algorithms, check this link: // https://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(srcImage, 0, 0, width, height, null); g.dispose(); // Re-encode image to target format ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(resizedImage, imageType, os); InputStream is = new ByteArrayInputStream(os.toByteArray()); // Set Content-Length and Content-Type ObjectMetadata meta = new ObjectMetadata(); meta.setContentLength(os.size()); if (JPG_TYPE.equals(imageType)) { meta.setContentType(JPG_MIME); } if (PNG_TYPE.equals(imageType)) { meta.setContentType(PNG_MIME); } // Uploading to S3 destination bucket System.out.println("Writing to: " + dstBucket + "/" + dstKey); s3Client.putObject(dstBucket, dstKey, is, meta); System.out.println("Successfully resized " + srcBucket + "/" + srcKey + " and uploaded to " + dstBucket + "/" + dstKey); return "Ok"; } catch (IOException e) { throw new RuntimeException(e); } } }

Amazon S3 は Event 呼び出しタイプを使用して Lambda 関数を呼び出します。ここで、AWS Lambda はコードを非同期に実行します。戻り値は重要ではありません。ただし、この場合、戻り値の型の指定を必要とするインターフェイスを実装するため、この例ではハンドラは戻り値として String を使用します。

前述のコード (S3EventProcessorCreateThumbnail.java という名前のファイル) を使用して、デプロイパッケージを作成します。必ず次の依存関係を追加してください。

  • aws-lambda-java-core

  • aws-lambda-java-events

これらは、aws-lambda-java-libs に掲載されています。

詳細については、「Java で Lambda 関数を作成するためのプログラミングモデル」を参照してください。

デプロイパッケージは、.zip ファイルまたはスタンドアロン .jar とすることができます。デプロイパッケージを作成するために、使い慣れた任意のビルドおよびパッケージ化ツールを使用できます。Maven ビルドツールを使用してスタンドアロン .jar を作成する方法の例については、「IDE なしで Maven を使用した .jar デプロイパッケージの作成 (Java)」および「Maven および Eclipse IDE を使用した .jar デプロイパッケージの作成 (Java)」を参照してください。Gradle ビルドツールを使用して .zip ファイルを作成する方法の例については、「.zip デプロイパッケージの作成 (Java)」を参照してください。

デプロイパッケージが作成されたことを確認したら、次のステップに進んで IAM ロール (実行ロール) を作成します。Lambda 関数の作成時にそのロールを指定します。

次のステップ

ステップ 2.2: 実行ロール (IAM ロール) を作成する

Python

このセクションでは、Python 関数の例を作成し、依存関係をインストールします。コードサンプルは Python ランタイムのバージョン 3.6 または 2.7 に準拠しています。このステップでは 3.6 ランタイムを前提としていますが、どちらも使用できます。

  1. テキストエディターを開き、次のコードをコピーします。以下のように、このコードはサイズ変更したイメージを同じイメージ名で異なるバケットにアップロードします。

    source-bucket/image.png -> source-bucketresized/image.png

    注記

    from __future__ ステートメントを使用すると、Python 2 または 3 と互換性のあるコードを作成できます。ランタイムバージョン 3.6 を使用している場合は、これを含める必要はありません。

    Copy
    from __future__ import print_function import boto3 import os import sys import uuid from PIL import Image import PIL.Image s3_client = boto3.client('s3') def resize_image(image_path, resized_path): with Image.open(image_path) as image: image.thumbnail(tuple(x / 2 for x in image.size)) image.save(resized_path) def handler(event, context): for record in event['Records']: bucket = record['s3']['bucket']['name'] key = record['s3']['object']['key'] download_path = '/tmp/{}{}'.format(uuid.uuid4(), key) upload_path = '/tmp/resized-{}'.format(key) s3_client.download_file(bucket, key, download_path) resize_image(download_path, upload_path) s3_client.upload_file(upload_path, '{}resized'.format(bucket), key)
  2. CreateThumbnail.py という名前でファイルを保存します。

  3. ソースコードがローカルホストにある場合は、それをコピーします。

    scp -i key.pem /path/to/my_code.py ec2-user@public-ip-address:~/CreateThumbnail.py

  4. SSH を使用して 64 ビット Amazon Linux インスタンスに接続します。

    ssh -i key.pem ec2-user@public-ip-address

  5. 次のステップに従って Python 3.6 と virtualenv をインストールします。

    1. sudo yum install -y gcc zlib zlib-devel openssl openssl-devel

    2. wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz

    3. tar -xzvf Python-3.6.1.tgz

    4. cd Python-3.6.1 && ./configure && make

    5. sudo make install

    6. sudo /usr/local/bin/pip3 install virtualenv

  6. pip3 を介してインストールされた仮想環境を選択します。

    /usr/local/bin/virtualenv ~/shrink_venv

    source ~/shrink_venv/bin/activate

  7. 仮想環境にライブラリをインストールします

    pip install Pillow

    pip install boto3

    注記

    AWS Lambda には、Python 向けの AWS SDK (Boto 3) が含まれるため、デプロイパッケージに含める必要はありませんが、ローカルテストのためにオプションで含めることはできます。

  8. lib および lib64 サイトパッケージの内容を .zip ファイルに追加します。次のステップは、Python ランタイムバージョン 3.6 を使用していた前提であることに注意してください。バージョン 2.7 を使用していた場合は更新する必要があります。

    cd $VIRTUAL_ENV/lib/python3.6/site-packages

    zip -r9 ~/CreateThumbnail.zip *

  9. .zip ファイルに Python コードを追加します。

    cd ~

    zip -g CreateThumbnail.zip CreateThumbnail.py

次のステップ

ステップ 2.2: 実行ロール (IAM ロール) を作成する

このページの内容: