AWS Lambda(for Ruby2.5)で画像合成をやってみた!
はじめに
株式会社プラハ(PrAha)のエンジニア、篠原です。
AWS re:Invent 2018で、AWS Lambda(for Ruby2.5)がリリースされましたね!
早速使ってみました。
AWS Lambda(for Ruby2.5)の詳細はこちら↓ https://aws.amazon.com/blogs/compute/announcing-ruby-support-for-aws-lambda/
今回はAWS Lambda(for Ruby2.5)で、画像に任意のテキストを合成するデモをハンズオン形式で共有します!
AWS Lambdaで合成した画像↓
今回の記事のリポジトリはこちら↓
https://github.com/praha-inc/composite-image-ruby25
想定読者
- AWS Lambdaを知っている、もしくは使ったことがある人
- AWS Lambdaを使ったことがないRubyist(これを機に使ってみましょう!)
- AWS Lambdaで画像合成をやってみたい人
- AWS Lambdaを使ってみたい人
- 株式会社プラハに興味がある人
ん?プラハってなんだ?という方はこちらへアクセス! https://www.praha-inc.com/ Wantedlyもやっています!https://www.wantedly.com/companies/praha-inc
準備
AWSアカウントを持っていること
AWS Lambdaとは
公式: https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html
簡潔にまとめると、自分の書いたプログラムを任意のタイミングで実行してくれるサーバです。
AWS Lambdaには無料枠があります。
1,000,000 件のリクエスト 400,000GB秒 (2019年2月15日現在)
単純に考えると
- 100万件のリクエストを並列に捌ける
- メモリ(RAM)1GBのPCが400,000秒動作する
上記のマシンを毎月無料で扱うことができます。 参照: https://aws.amazon.com/jp/lambda/pricing/
割り当てるメモリ量は関数に応じて変更可能です(最小128MB~最大3008MB)。
無料で画像処理のみ行うマシンが欲しい場合、これで十分なのではないでしょうか。
AWS Lambdaを使用するユースケース
例えば、以下のようなユースケースが考えられます。
Heroku(APIサーバ)からLambdaを実行し、結果を受け取るようなケースです。
Herokuのスペックは無料枠だとRAMが512MB(2019年2月20日現在)。
そこで、画像合成の処理のみをLambdaに委譲し、Herokuの負担を抑えられることが期待できます(要検証)。
画像合成をするLambda関数を作る
では、Ruby2.5で画像処理を行うLambda関数を作ってみましょう!
Lambda関数を作成する
AWSマネジメントコンソールのLambdaにアクセス
https://ap-northeast-1.console.aws.amazon.com/lambda/
Lambda関数を作成しましょう。
入力項目 | 設定値 |
---|---|
名前 | CompositeImageRuby25 |
ランタイム | Ruby2.5 |
ロール | 既存のロールを選択 |
既存のロール | lambda_basic_execution |
関数を作成ボタンを押下。
作成したLambda関数の詳細ページが表示されます。
また、作成したLambda関数はCloudWatchLogsにアクセス可能なことがわかります。
画像合成後のファイル保存先のS3バケットを作成する
AWSマネジメントコンソールからいい感じにぽちぽちっと。 https://console.aws.amazon.com/s3/home?region=ap-northeast-1
※ここで作成したバケット名は、後述するプログラム上で扱います。
画像合成プログラムの実装
お好みのエディタを立ち上げて、まずはLambdaで実行するプログラムを書いていきます。 プロジェクトのディレクトリ構成は、先程示したリポジトリを参照して下さい。 (再掲)https://github.com/praha-inc/composite-image-ruby25
Rubyはバージョンを2.5系を使用してください。 (バージョンが違う場合、Lambda環境で実行できない可能性があります)
環境構築
$ mkdir composite_image_ruby25 && cd composite_image_ruby25 $ gem install bundler $ bundle init $ vim Gemfile
source 'https://rubygems.org' gem 'aws-sdk-s3' gem 'mini_magick'
$ bundle install --path vendor/bundle
画像合成プログラムからAWS S3へPutするための認証周りの設定
$ direnv edit . // direnvを使用していない場合は.env.copyを参照して環境変数を設定してください $ direnv allow
export AWS_ACCESS_KEY_ID=AWSマネジメントコンソールで発行したID export AWS_SECRET_ACCESS_KEY=AWSマネジメントコンソールで発行したSECRET
画像合成プログラムを書く
任意のテキストの画像合成後、S3に画像をアップロードします。
require 'aws-sdk-s3' require './image_helper' def lambda_handler(event:, context:) s3 = Aws::S3::Resource.new(region: 'ap-northeast-1') bucket_name = 'YOUR_BUCKET_NAME' file_name = 'helloworld.png' # Upload Image to S3 file = ImageHelper.build(event['message']).tempfile.open.read s3.bucket(bucket_name).object(file_name).put(body: file) # Get Image from S3 object = s3.bucket(bucket_name).object(file_name) { statusCode: 200, url: object.public_url, } end # for exec local if __FILE__ == $0 lambda_handler(event: { 'message' => 'Hello, PrAha!' }, context: nil) end
ローカルで実行
$ bundle exec ruby lambda_function.rb
AWSマネジメントコンソールのS3を参照して画像がアップロードされていることが確認できればOK
画像合成プログラムをAWS Lambdaにデプロイ
ローカルからAWS Lambdaにデプロイするための設定をする
先程取得した、AWS_ACCESS_KEY_ID、とAWS_ACCESS_SECRETをaws-cliの設定ファイルに記述します。
$ aws configure AWS Access Key ID [****]: AWS Secret Access Key [****]: Default region name [ap-northeast-1]:
ローカルからAWS Lambdaにデプロイ
aws-cliの設定後、プロジェクトディレクトリのルートで下記を実行し 先程作成したLambda関数(CompositeImageRubuy25)にデプロイします。
$ zip -r function.zip lambda_function.rb image_helper.rb assets vendor $ aws lambda update-function-code --function-name CompositeImageRuby25 --zip-file fileb://function.zip { "LastModified": "2019-02-20T10:14:42.632+0000", "Version": "$LATEST", "Runtime": "ruby2.5", "FunctionName": "CompositeImageRuby25", "CodeSize": 5658411 ...略 }
動作確認
AWSマネジメントコンソールで先ほど作成したLambda関数を開いてください。
デプロイに成功すると恐らく以下のように表示されていると思います。
テストを実行
テストを行う前に、AWSマネジメントコンソールの右上からテストイベントの設定を行います。 「テストイベントの設定」を押下してください。
テストイベントの設定で以下のように入力してください。 入力後、作成を押下。
作成後、「テスト」を押下してください。
恐らくエラーが発生するので後述の章で対処していきましょう。
エラーの対処
タイムアウト時間の設定
以下のようなエラーが発生する場合
Lambdaの実行時間が足りないので、基本設定でタイムアウト時間を10秒にしましょう。
再度、「テスト」を押下してください。
S3への書き込み権限の付与
以下のようなエラーが発生する場合
LambdaからS3への書き込みをする権限がないため、書き込みを可能にするよう権限を付与します。
LambdaからS3へのアクセス権を付与する
「実行ロール」を確認してください。
「実行ロール」からカスタムロールの作成を押下。 ページが表示されたら、任意のロール名を入力(ここでは lambda_write_s3)。「許可」を押下。
作成後、以下のように表示されます。
「lambda_write_s3」をクリックし、「ポリシーをアタッチします」を押下してください。 「AmazonS3FullAccess」にチェックボックスを入れて、ポリシーのアタッチを押下してください。
AWS Lambdaのマネジメントコンソールに戻り、ロールを新規に作成したものに変更し、右上の保存を押下してください。
以下のように表示されればOKです(LambdaからS3へのアクセス権が付与されたことがわかります)。
再度、「テスト」を実行
実行に成功することを確認します。
最後に、画像がS3にアップロードされていることが確認できれば完成です!
おわりに
今回はAWS Lambda(for Ruby2.5)で画像合成を行いました。いかがでしたでしょうか。 Lambdaを使ったことがない人、Lambdaで画像合成をやってみたい人の参考になれば幸いです。
不明点、指摘点などありましたらコメントをお待ちしております!
次はAWS Lambdaで動画合成をやってみた、を書く予定です!
Happy Coding!