PrAha Inc.

PrAha Inc. のブログ、あるいは社員の観察日記

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で合成した画像↓

hellopraha.png

今回の記事のリポジトリはこちら↓

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を使用するユースケース

例えば、以下のようなユースケースが考えられます。 スクリーンショット 2019-02-20 21.06.55.png

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関数を作成しましょう。

スクリーンショット 2019-02-20 19.01.24.png

入力項目 設定値
名前 CompositeImageRuby25
ランタイム Ruby2.5
ロール 既存のロールを選択
既存のロール lambda_basic_execution

関数を作成ボタンを押下。

作成したLambda関数の詳細ページが表示されます。 スクリーンショット 2019-02-15 13.47.09.png

また、作成したLambda関数はCloudWatchLogsにアクセス可能なことがわかります。

画像合成後のファイル保存先のS3バケットを作成する

AWSマネジメントコンソールからいい感じにぽちぽちっと。 https://console.aws.amazon.com/s3/home?region=ap-northeast-1

スクリーンショット 2019-02-20 19.44.14.png

※ここで作成したバケット名は、後述するプログラム上で扱います。

画像合成プログラムの実装

お好みのエディタを立ち上げて、まずは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関数を開いてください。

デプロイに成功すると恐らく以下のように表示されていると思います。 スクリーンショット 2019-02-21 18.05.32.png

テストを実行

テストを行う前に、AWSマネジメントコンソールの右上からテストイベントの設定を行います。 「テストイベントの設定」を押下してください。 スクリーンショット 2019-02-21 18.06.52.png

テストイベントの設定で以下のように入力してください。 スクリーンショット 2019-02-21 18.08.02.png 入力後、作成を押下。

作成後、「テスト」を押下してください。

恐らくエラーが発生するので後述の章で対処していきましょう。

エラーの対処

タイムアウト時間の設定

以下のようなエラーが発生する場合 スクリーンショット 2019-02-20 19.05.36.png

Lambdaの実行時間が足りないので、基本設定でタイムアウト時間を10秒にしましょう。 スクリーンショット 2019-02-21 18.12.13.png

再度、「テスト」を押下してください。

S3への書き込み権限の付与

以下のようなエラーが発生する場合 スクリーンショット 2019-02-20 19.08.58.png

LambdaからS3への書き込みをする権限がないため、書き込みを可能にするよう権限を付与します。

LambdaからS3へのアクセス権を付与する

「実行ロール」を確認してください。 スクリーンショット 2019-02-21 18.15.42.png

「実行ロール」からカスタムロールの作成を押下。 ページが表示されたら、任意のロール名を入力(ここでは lambda_write_s3)。「許可」を押下。

作成後、以下のように表示されます。

スクリーンショット 2019-02-20 19.11.18.png

「lambda_write_s3」をクリックし、「ポリシーをアタッチします」を押下してください。 「AmazonS3FullAccess」にチェックボックスを入れて、ポリシーのアタッチを押下してください。 スクリーンショット 2019-02-21 18.19.58.png

AWS Lambdaのマネジメントコンソールに戻り、ロールを新規に作成したものに変更し、右上の保存を押下してください。

以下のように表示されればOKです(LambdaからS3へのアクセス権が付与されたことがわかります)。 スクリーンショット 2019-02-21 18.21.38.png

再度、「テスト」を実行

実行に成功することを確認します。 スクリーンショット 2019-02-21 18.23.15.png

最後に、画像がS3にアップロードされていることが確認できれば完成です!

おわりに

今回はAWS Lambda(for Ruby2.5)で画像合成を行いました。いかがでしたでしょうか。 Lambdaを使ったことがない人、Lambdaで画像合成をやってみたい人の参考になれば幸いです。

不明点、指摘点などありましたらコメントをお待ちしております!

次はAWS Lambdaで動画合成をやってみた、を書く予定です!

Happy Coding!