AWS Lambdaで画像ファイル加工~環境構築から実行確認まで~ 手順紹介

通常、プログラムを実行するためには、サーバーOSやアプリケーションサーバーソフトウェアと環境設定が必要です。こうした実行環境の準備の手間を大幅に削減してくれるのが、「AWS Lambda(ラムダ)」です。AWS Lambdaの概要については「サーバーレスでプログラムを実行できる「AWS Lambda」とは」をご参照ください。
実際にLambdaを利用するにはLambda関数の仕様や登録手順、環境設定など、多くの関連知識が必要になります。中にはAWSのサイトで紹介されているチュートリアルを動かして初めて理解できることも多く、Lambdaを利用する際の課題でもあります。
そこで本コラムでは、用例毎に環境構築からLambda関数の作成および動作確認までの一連の作業を取り上げて解説し、Lambdaの利用に必要な知識を身に着けていただいて少しでもLambda利用のハードルを下げるご支援をしたいと思います。
Lambdaの活用用途は幅広いのですが、今回は「ファイル処理」に関するLambdaの作成手順を解説します。
具体的には、以下のような画像ファイルの加工処理を行うLambdaの作成手順を解説します。

Lambdaの処理内容

Amazon S3にアップロードされた画像ファイルを縮小加工してサムネイル画像としてAmazon S3へ再アップロードする

本記事は、「チュートリアル:Amazon S3 で AWS Lambda を使用する別ウィンドウで開きます」のPython3用のサンプルコード別ウィンドウで開きますを元に手順を詳細化して解説したものです。そのため、文中のLambdaの作成手順はPython3.8向けの解説となります。

1.画像ファイル加工処理Lambdaの動作概要

動作の全体像を以下に示します。

動作概要

Amazon S3の所定のバケットに画像ファイルがアップロードされると画像ファイル加工処理用Lambdaが起動されます。
起動されたLambda関数では次のような処理を実施します。
①引数からアップロードされたS3のバケットとkey情報を取得。
②バケットとkeyを使ってアップロードされた画像ファイルをS3から取得し、ローカルエリアに一時保存。
③保存した画像ファイルを縮小加工。縮小した画像ファイルをS3へアップロード

2.Lambdaパッケージ作成環境構築

2.1.Lambda作成方法について

Lambda作成方法には次の2通りがあります。
①AWS Lambdaコンソールで直接コードを作成
②外部ライブラリとLambda関数をパッケージ化したzipファイルを作成し、AWS Lambdaにアップロード

①ではAWSの操作の他、基本的な処理が出来るよう以下の機能が提供されています。

  • AWS-SDK(AWSを操作するためのライブラリ)
  • http
  • https
  • child_process

これら以外の機能を利用する場合、②での作成となります
今回ケースでは、画像データの縮小に画像処理ライブラリを使用するため、②での作成となります。

2.2.Lambda作成環境について

AWS Lambdaはlinux環境で動作するため、Lambdaパッケージ作成環境はlinux環境が推奨されています。今回のケースではOSにubuntuを選択したAmazon EC2上で実施しました。

2.3.Lambdaパッケージ作成

2.3.1事前作業

Amazon EC2のデフォルト環境ではpip, zip, python3.8がインストールされておらずこれらのインストールが必要になります。

pipのインストール

$ sudo apt-get install python-pip

zipのインストール

$ sudo apt install zip

python3.8のインストール

$ sudo apt install python3.8
2.3.2Lambdaパッケージ作成環境構築

Pythonの仮想環境機能:virtualenvを使って画像ファイル加工用Lambdaパッケージ作成環境を構築します。

virtualenv / virtualenvwrapperをインストールします。

$ sudo apt install virtualenv virtualenvwrapper

virtualenvの作業フォルダを作成し、移動します。

$ mkdir -p /tmp/virtualenv
$ cd /tmp/virtualenv

python3.8の仮想環境の作成

EC2環境ではデフォルトでpython2.7の仮想環境が作成されるため、python3.8の仮想環境を作成する場合は、-pオプションを使ってpython3.8を指定します。
$ virtualenv -p /usr/bin/python3.8 v-env

作成した仮想環境を起動します。

$. v-env/bin/activate

仮想環境に外部ライブラリPillow, boto3をインストールします。

(v-env) ubuntu:/tmp/virtualenv$ pip install Pillow boto3
Pillow:pythonの画像処理ライブラリ
boto3:python用AWS SDK(PythonでAWSを操作するためのライブラリ)
(Lambdaコンソールで直接コードを作成する場合は標準装備されていますが、パッケージアップロードの場合はそのリンクから外れるため、外部ライブラリとしてインストールする必要があります)

3.Lambdaパッケージの作成

3.1.外部モジュールのパッケージ化

Pillowとboto3モジュールをパッケージ化したlambda_function.zipを作成します。

(v-env) ubuntu:/tmp/virtualenv$ cd $VIRTUAL_ENV/lib/python3.8/site-packages
(v-env) ubuntu:/tmp/virtualenv/v-env/lib/python3.8/site-packages$ zip -r9 ${OLDPWD}/lambda_function.zip .

3.2.Lambda関数の作成

元のフォルダに移動します。

(v-env) ubuntu:/tmp/virtualenv/v-env/lib/python3.8/site-packages$ cd ${OLDPWD}

viエディタでlambda_function.pyを作成します。

(v-env) ubuntu:/tmp/virtualenv$ vi lambda_function.py

lambda_function.pyのコードを以下に示します。

import boto3	
import os	
import sys	
import uuid	
from urllib.parse import unquote_plus	
from PIL import Image	
import PIL.Image	
	
s3_client = boto3.client('s3')	//S3クライアントを取得(注2)
	
def resize_image(image_path, resized_path):	//Pillowの機能を使用した画像データ処理用関数
    with Image.open(image_path) as image:	//画像ファイルから画像データを取得
        image.thumbnail(tuple(x / 2 for x in image.size)	//画像データサイズを1/2に縮小
        image.save(resized_path)	//Lambda内の一時保存先に保存
	
def lambda_handler(event, context):	//Lambdaから最初に呼びされるハンドラ関数
    for record in event['Records']:	
        bucket = record['s3']['bucket']['name']	//引数からS3のバケット名抽出(注1)
        key = unquote_plus(record['s3']['object']['key']	//引数からS3のkey(フォルダ名/ファイル名)抽出 (注1)
        splitkey = key.split('/')	//keyのフォルダ名/ファイル名を分離
        newkey = key.replace(splitkey[0], 'thumbnails')	//thumbnails/ファイル名としたnewkeyを作成
        tmpkey = key.replace('/', '')	
        download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey)	//S3からダウンロードしたファイルの保存先を設定
        upload_path = '/tmp/resized-{}'.format(tmpkey)	//加工したファイルの一時保存先を設定
        s3_client.download_file(bucket, key, download_path)	//S3からファイルをダウンロード(注2)
        resize_image(download_path, upload_path)	//画像データ処理用関数を呼び出す
        s3_client.upload_file(upload_path, bucket, newkey)	//縮小加工したファイルをS3にアップロード(注2)
上記コードはPython3用のサンプルコード別ウィンドウで開きますを流用改造したものです。
サンプルコードからの変更点は以下になります。
縮小処理した画像ファイルのS3のアップロード先を以下のように変更。
・別のバケット ⇒ 同一バケット内の別フォルダ

(注1)
関数:lambda_handlerの引数:eventには呼び出し元からのメッセージが設定されています。S3ではバケットやkeyの値などが設定されます。
詳細はAmazon S3 通知イベント別ウィンドウで開きますを参照してください。

(注2)
LambdaからS3へのアクセスにはAWS SDK for Python(boto3)を使用します。
S3へのファイルのアップロード、ダウンロードはS3のクライアントAPIを使用します。それぞれの手順を以下に示します。

ダウンロード手順

import boto3
s3 = boto3.client('s3')
s3.download_file(bucket, key, download_filename)

アップロード手順

import boto3
s3 = boto3.client('s3')
s3.upload_file(upload_filename, bucket, key)

boto3全体のドキュメントは「Boto 3 Documentation別ウィンドウで開きます」を参照してください。
S3 APIの詳細については「Available Services S3別ウィンドウで開きます」を参照してください。

3.3.Lambdaファイルを加えたパッケージの作成

lambda_function.zipに作成したLambdaファイルを追加します。

(v-env) ubuntu:/tmp/virtualenv$ zip -g lambda_function.zip lambda_function.py
  adding: lambda_function.py (deflated 55%)

これでパッケージ作成作業は完了です。以下のコマンドで仮想環境から抜けてください。

(v-env) ubuntu:/tmp/virtualenv$ deactivate

仮想環境から抜けた後は/tmp/virtualenvフォルダ上にlambda_function.zipファイルが作成されていることを確認してください。
最後に、作成したlambda_function.zipをSCPコマンドなどでLambdaコンソールを操作している作業用PCへ転送します。

4.S3設定

4.1.バケットの作成

S3に画像ファイル用のバケットを作成します。
S3コンソールから「+バケットを作成する」を選択してバケットを新規作成します。

バケット名に「lambda-test-2020」と入力し、バケットを作成します。

4.2.アップロードフォルダの作成

作成したバケット「lambda-test-2020」を開きます。
「+フォルダの作成」を選択してアップロード用フォルダを作成します。

フォルダ名に「images」と入力し、フォルダを作成します。

4.3.ダウンロード用フォルダの作成

同様の手順でダウンロード用フォルダを作成します。
lambda_function.pyのコードに合わせ、フォルダ名は「thumbnails」で作成します。

5.Lambdaパッケージのアップロード

5.1.関数の作成

Lambdaコンソールから「関数の作成」ボタンを押下します。「関数の作成」画面のオプションの中から「一から作成」を選択します。
「基本的な情報」の設定項目に以下を設定します

  • 「関数名」に「ThumbnailCreation」と入力
  • 「ランタイム」にドロップダウンリストから「Python3.8」を選択
  • 折り畳まれている「実行ロールの選択または作成」を開く

「実行ロールの選択または作成」の設定でS3へのアクセス権を設定します。

  • 「実行ロール」の選択肢から「AWSポリシーテンプレートから新しいロールを作成」を選択
  • 「ロール名」に「s3-read-write-access」を設定
  • 「ポリシーテンプレート・オプション」のドロップダウンメニューを開く

  • 「ポリシーテンプレート・オプション」のドロップダウンメニューから「Amazon S3 オブジェクトの読み取り専用アクセス権限」を選択

最後に、画面右下の「関数の作成」を押下します。

登録したLambda関数「ThumbnailCreation」のメニュー画面が表示されます。

5.2.トリガーの設定

登録したLambda関数「ThumbnailCreation」のメニュー画面から「+トリガーを追加」ボタンを押下します。

「トリガーの選択」のドロップダウンリストから「S3」を選択します。

以下の設定を行い、最後に「追加」ボタンを押下します。

  • 「バケット」にドロップダウンリストから「4.1. バケットの作成」で作成したバケット名「lambda-test-2020」を選択
  • 「イベントタイプ」に「すべてのオブジェクト作成イベント」を選択
  • 「プレフィックス」に「4.2. アップロードフォルダの作成」で作成したフォルダ名「images」を設定
  • 「サフィックス」にJPEGファイルの拡張子 .jpg を設定
画面一番下にある「トリガーの有効化」のチェックボックスにはチェックを入れないようにしてください。

5.3.Lambdaパッケージのアップロード

Lambda関数「ThumbnailCreation」のメニュー画面から「関数コード」の設定を実施します。

「コードエントリタイプ」のドロップダウンリストから「.zipファイルをアップロード」を選択します。

「関数パッケージ」の「アップロード」ボタンを押下し、ファイルの入力画面から「3. Lambdaパッケージの作成」で作成したlambda_function.zipを選択します。

画面右上の「保存」ボタンを押下し、zipファイルのアップロードを実施します。

5.4.S3アクセス権の追加

「5.1. 関数の作成」で作成した実行ロールは読み取り専用のアクセス権なので、書き込み用アクセス権を追加します。

「ThumbnailCreation」のメニュー画面を「実行ロール」の表示位置までスクロールします。
「既存のロール」の「IAMコンソールでs3-read-write-accessロールを表示します」をクリックします。

IAMの「ロール」-「s3-read-write-access」のメニュー画面が開きます。
「アクセス権限」タブの「Permissions Policies」のリストから「AWSLambdaS3ExecutionRole-…」を選択します。

「AWSLambdaS3ExecutionRole-…」の詳細設定画面が開いたら「ポリシーの編集」ボタンを押下します。

「S3(1つのアクション)」をクリックし、折り畳まれている情報を表示します。

「アクション」をクリックし、折り畳まれている情報を表示します。

「アクセスレベル」の中の「書き込み」を選択し、折り畳まれている情報を表示します。

「PutObject」にチェックを入れます。
画面右下の「ポリシーの確認」ボタンを押下します。

S3の「アクセスレベル」が「制限:読み込み、書き込み」となっていることを確認し、画面右下の「変更の保存」ボタンを押下します。

これで、S3の書き込み用アクセス権が追加されます。

6.Lambdaのテスト実行

Lambdaコンソール上でLambdaのテストを実施できます。
ここではテスト実行までの手順を解説します。

6.1.テストイベントの設定

Lambda関数「ThumbnailCreation」のコンソール画面から「テストイベントの設定」を選択します。

「テストイベントの設定」画面で以下を設定します。

  • 「新しいテストイベントの作成」を選択
  • 「イベントテンプレート」のドロップダウンリストから「Amazon S3 Put」を選択

このイベントテンプレートは、Lambdaテスト実行時、Lambda関数の引数:eventとして設定されます。

イベントテンプレートを以下のように修正して、画面右下の「保存」ボタンを押下します。

  • "bucket"の"name"と"arn"を「4.1. バケットの作成」で作成したバケット「lambda-test-2020」に変更
  • "key"を「5.2. トリガーの設定」で作成した「プレフィックス」と「サフィックス」に合わせて「images/sample.jpg」とする

6.2.テスト実行

6.2.1.画像ファイルのアップロード

S3のバケット「lambda-test-2020」のフォルダ「images」に ファイル名「sample.jpg」の画像ファイルをアップロードします。

JPEG画像ファイルを用意し、ファイル名をsample.jpgとします。
S3コンソールからバケット「lambda-test-2020」内のフォルダ「images」へ移動します。
「アップロード」ボタンを押下します。

「アップロード」操作画面が開くので、用意したJPEG画像ファイル「sample.jpg」をドラッグアンドドロップ操作で追加します。

ファイルが追加されたら「アップロード」ボタンを押下します。

Imagesフォルダ上にsample.jpgが保存されます。

6.2.2.実行

Lambda関数「ThumbnailCreation」のコンソール画面の「テスト」ボタンを押下してテストを実行します。

「実行結果:成功」と表示されればLambdaの実行が正常終了したことになります。

「実行結果:失敗」と表示された場合は、表示されたログから原因を解析してください。

テストが成功すると、S3のバケット「lambda-test-2020」内のフォルダ「thumbnails」にサムネイル画像ファイル「sample.jpg」が保存されます。元画像とサイズを比較すると1/2の大きさに縮小されていることが確認できます。

6.2.3.ログ確認

テスト実行結果の「ログ」ボタンを押下するとCloudWatchに保存されたLambda関数「ThumbnailCreation」のロググループにジャンプします。

ログストリームのリストに表示されているファイルをクリックすると、Lambda関数のログ詳細を見ることが出来ます。

7.動作試験

「6.2.Lambdaのテスト実行」で「実行結果:成功」を確認できたら「5.2.トリガーの設定」で仮登録しているトリガーを有効にします。

7.1.トリガーの有効化

Lambda関数「ThumbnailCreation」のコンソール画面から「S3」設定項目の右側にあるトグルスイッチを「無効」から「有効」に切り替えてください。
切り替え後、画面右上にある「保存」ボタンを押下してください。

7.2.画像ファイルアップロードとサムネイルファイルの保存確認

「6.2.1.画像ファイルのアップロード」と同様の手順で画像ファイルをバケット「lambda-test-2020」のフォルダ「images」上にアップロードします。ファイル名は拡張子を .jpg とする以外は自由に設定できます。
画像ファイルアップロード後、フォルダ「thumbnails」に同じファイル名で元の1/2に縮小されて保存されていることを確認してください。

7.3.ログ確認

「6.2.3. ログ確認」と同様にLambdaの実行結果をCloudWatchに保存されたログで確認できます。

Lambda関数「ThumbnailCreation」のコンソール画面から「モニタリング」タブを開き、「CloudWatchのログを表示」ボタンを押下してください。
CloudWatch のLambda関数「ThumbnailCreation」のロググループにジャンプします。

あとがき

S3にアップロードされた画像を縮小加工して保存するLambdaの作成手順を環境構築から実行確認まで解説しました。特に外部ライブラリを使用したLambdaの作成からパッケージ化したzipファイルのアップロードまでの手順が理解できたかと思います。
まだまだLambdaの活用方法はたくさんありますので、是非チャレンジしてみてください。
次回はDynamoDBを使ったLambdaの作成手順について解説致します。

Amazon Web Services(AWS)、Microsoft Azureの
導入支援サービスのご相談、お問い合わせをお待ちしております。

ページ上部へ戻る