Serverless Frameworkでバイナリデータを処理するアーキテクチャを構築したかった
こんにちは。AWSチーム百木田です。
サーバーレス、してますか?
この度、「
そして何かツールを使って楽にデプロイしたいと思い、今回はServerless Frameworkを利用してやってみることにしました。
環境
- OS(VM): CentOS Linux release 7.2.1511 (Core)
- Node Version: 7.5.0
- Serverless Version: 1.8.0
準備
Serverlessの定義ファイル作成
Serverlessのセットアップについては省略させていただきます。’serverless’コマンドが実行できる前提です。
‘serverless.yml’を作成します。
定義している内容は以下です。
- LambdaからS3にデータを置くためのIAMロールを定義
- POSTで受けてLambda処理を行うAPI Gatewayを定義
- 画像を保存するS3 Bucketを定義
注)S3バケット名の部分は変更してください。
service: saveImage
provider:
name: aws
runtime: python2.7
stage: dev
region: ap-northeast-1
iamRoleStatements:
- Effect: "Allow"
Action:
- "s3:Put*"
Resource:
Fn::Join:
- ""
- - "arn:aws:s3:::${self:custom.bucketName}/*"
environment:
'bucketName': '${self:custom.bucketName}'
# バケット名を変数として宣言
custom:
bucketName: BUCKET_NAME
# APIゲートウェイの設定を定義
functions:
save:
handler: handler.handler
events:
- http:
path: save
method: post
# S3バケットを定義
resources:
Resources:
myImageBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:custom.bucketName}
Outputs:
RdsLogs:
Description: "Bucket for images"
Value:
Ref: "myImageBucket"
タイトルで「してみた」にできなかったのには理由があり、残念なことに肝心のバイナリデータサポートの設定は現時点でServerlessでは対応していませんでした。そのためプラグインを使用するか他の方法で設定する必要があります。今回は泥臭くデプロイ後にマネジメントコンソールで設定することにします。
Lambda実行コードを作成
Lambdaでの処理は受け取った画像データをS3にアップロードするという簡単なものにしました。
# -*- coding: utf-8 -*-
import os
import logging
import datetime
import base64
import boto3
logger = logging.getLogger()
logger.setLevel(logging.INFO)
s3 = boto3.client('s3')
BUCKET_NAME = os.environ['bucketName']
def handler(event, context):
todaydetail = datetime.datetime.today()
FILENAME = (todaydetail.strftime("%Y%m%d-%H%M%S") + '.jpg')
dec_save(data = event['body'], FILENAME = FILENAME)
s3.upload_file('/tmp/' + FILENAME, BUCKET_NAME, FILENAME)
os.remove('/tmp/' + FILENAME)
responce = {
"statusCode": 200,
"body": "Upload Sccessful \n"
}
logger.info(responce)
return responce
# ------------ バイナリデータをデコードして/tmpに保存する -------------
def dec_save(data, FILENAME):
dec_data = base64.b64decode(data)
f = open('/tmp/' + FILENAME,'w')
f.write(dec_data)
f.close()
return
ここではデータを’/tmp’に一度保存していますがもちろん受け取ってそのままS3にあげちゃってもOKです。
デプロイ
$ serverless deploy
バイナリデータサポートを設定
‘serverless deploy’するとS3バケットやAPI Gateway、Lambdaといったリソースが作成されているかと思います。その後、API Gatewayのマネジメントコンソールからバイナリサポートのバイナリメディアタイプに’image/jpg’などPOSTで受ける’Content-Type’に合わせた値を設定します。
バイナリサポート設定後のAPIをデプロイするために再度’serverless deploy’をします。再度デプロイしても手動で設定したバイナリサポートの設定は消えません。
これで設定は完了です。
実際に試してみる
お手軽に試すにはローカル端末から以下のコマンドを実行します。
$ curl -X POST \
-H "Accept: image/jpg" \
-H "Content-Type: image/jpg" \
--data-binary "@image.jpg" \
"https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/save"
‘Upload Sccessful’が表示され、S3の指定バケットにファイルが保存されています。
まとめ
今回はServerless Frameworkを利用しましたが他にもSAMやApex、Lamveryなどツールが出ているので今後試していきたいと思います。Serverless Frameworkも順次アップデートされているので今後楽しみです。
ありがとうございました。