AWS S3互換であるminioと、lamda function開発用のdocker imageであるdocker-lambdaを使って、ローカルで開発環境を作ろうというお話です。
Minio
MinioはAWS S3互換のObject Strageで、ローカルにS3環境を作ることができます。
公式ドキュメントも用意されており、Dockerがあれば手軽にはじめられます。
minio server
サーバーの立ち上げは以下のコマンド。
$ docker run \
--name minio
-p 9000:9000 \
-p 9001:9001 \
-e "MINIO_ROOT_USER=minioadmin" \
-e "MINIO_ROOT_PASSWORD=minioadmin" \
quay.io/minio/minio server /data --console-address ":9001"
minio client
このminioにはコマンドも用意されている。これによってローカルで立てたminioサーバーに対してコマンドから操作を行うことができる。
mcを起動後、さきほどminio serverを立ち上げたときに表示されていたmc
ではじまるコマンドをコピペする。
これでminio serverとの接続が完了。この先はコマンドでminio serverを操作することが可能となる。
$ docker pull minio/mc
$ docker run --name mc -it --entrypoint=/bin/sh minio/mc
# mc alias set minio http://minio:9000 minioadmin minioadmin
docker-lambda
そしてlambda fuction開発用のdocker imageであるdocker-lambda。
Amazon Lambda Functionの中身はAmazon linuxらしく(知らなかった)、それをDocker内で環境構築し、必要なパッケージをインストールしてzipで固めて〜...を簡単に行えるようにしたもの。
コマンドの基本形は以下
$ docker run --rm -v <code_dir>:/var/task lambci/lambda:<runtime> <filename>.<funcname>
以下のファイルを適当なディレクトリで作成。
def my_handler(event, context):
message = 'Hello {} {}!'.format(event['first_name'],
event['last_name'])
return {
'message' : message
}
上記ファイルがあるディレクトリで以下のコマンドを叩くと、それでテストができる
$ docker run --rm -v "$PWD":/var/task lambci/lambda:python3.7 function.my_handler \
'{"first_name": "Kenji", "last_name": "Yamada"}'
上記コマンドを叩いた場合はイベントが起こった前提でのテストができ、即終了となるが、DOCKER_LAMBDA_STAY_OPEN=1
というオプションをつけることでAPIサーバーとしてdocker-lambdaを起動することができる。
$ docker run --rm \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
-v "$PWD":/var/task \
lambci/lambda:python3.7 \
function.my_handler
以下のコマンドでイベントを投げることができる。
$ curl -d '{"first_name": "Kenji", "last_name": "Yamada"}' http://localhost:9001/2015-03-31/functions/myfunction/invocations
本題
ここまでが今回使うツールの説明である。
そして上記で説明したものはだいたい検索すれば出てくる。
今回やりたいことは以下の2つ
- Minioにはwebhookの設定があるらしい
- Minioにファイルをおいたタイミングでdocker-lambdaを動かしたい
ネットワークの設定
複数のコンテナを立ち上げて通信するため、まずはネットワークの設定を行う
$ docker network create minio-lambda-net
minio サーバーを立ち上げ
使い回せるようにdocker-composeファイルを用意した
ここからcloneして立ち上げる
$ docker-compose up
lambdaをAPIサーバーとして立ち上げ
まず、以下のようなlambda functionを作成する。
内容はシンプルに、S3にファイルをおいたタイミングでS3の情報を表示するだけ。
今回はS3の代わりにMinioを使っているので、endpointにminioのurlをしていする。
from __future__ import print_function
import os
import json
import urllib
import boto3
print('Loading function')
print('AWS_ACCESS_KEY_ID: ', os.environ.get('AWS_ACCESS_KEY_ID'))
print('AWS_SECRET_ACCESS_KEY: ', os.environ.get('AWS_SECRET_ACCESS_KEY'))
s3_endpoint_url = 'http://minio:9000'
#http://boto3.readthedocs.io/en/latest/reference/services/s3.html#client
s3 = boto3.client('s3', endpoint_url=s3_endpoint_url)
def lambda_handler(event, context):
print(event)
bucket_name = event['Records'][0]['s3']['bucket']['name']
print('==== bucket information =====')
print(bucket_name)
print('=============================')
#https://github.com/bloomberg/chef-bcs/blob/master/cookbooks/chef-bcs/files/default/s3-example-boto3.py
print('==== your bucket list ====')
buckets = s3.list_buckets()
for bucket in buckets['Buckets']:
print(bucket.get('Name'))
print('==== file list in bucket ====')
# https://github.com/boto/boto3/issues/134
AWS_S3_BUCKET_NAME = 'test'
s3_resource = boto3.resource('s3', endpoint_url=s3_endpoint_url)
bucket = s3_resource.Bucket(AWS_S3_BUCKET_NAME)
result = bucket.meta.client.list_objects(Bucket=bucket.name, Delimiter='/')
for o in result.get('Contents'):
print(o.get('Key'))
print('==== uploaded file ====')
for rec in event['Records']:
print(rec['s3']['object']['key'])
print('=============================')
print("Received event: " + json.dumps(event, indent=2))
サーバーの起動は以下のコマンド。
$ docker run --rm \
--name d-lambda \
--net=minio-lambda-net \
-p 3000:3000 \
-e AWS_ACCESS_KEY_ID=minioadmin \
-e AWS_SECRET_ACCESS_KEY=minioadmin \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-v "$PWD":/var/task \
lambci/lambda:python3.7 \
function.lambda_handler
Minio serverのwebhookの設定
Minio serverにはBucket Notificationという機能があり、方法は色々あるがwebhookを使ってMinioでのイベントを通知してみようというお話。
注意すべき点はendpointの設定。さっきd-lambdaという名前でサーバーを起動しているので、ホスト名をd-lambdaにする。
# mc alias set minio http://minio:9000 minioadmin minioadmin
# mc admin config set minio notify_webhook:1 queue_limit="0" endpoint="http://d-lambda:3000/2015-03-31/functions/myfunction/invocations" queue_dir=""
ここで一度サーバーを再起動するように指示されるので、それに従う。
# mc admin service restart myminio
# mc mb minio/test
# mc event add minio/test arn:minio:sqs::1:webhook --event put --suffix .mp4
上記の設定を行うことで、testという名前のbucketに*.mp4というファイルをアップロードしたとき、webhookの通知を行うことができる。
以上で設定は完了となる。
http://localhost:9000 にアクセスするとMinioのWebUIが表示されるので、そこからファイルをアップロードしてみましょう。
lambdaを立てたコンソールで結果が見えるはずです。
参考
- https://docs.min.io/docs/minio-docker-quickstart-guide.html
- https://docs.min.io/docs/minio-client-complete-guide.html
- https://github.com/minio/minio/tree/master/docs/orchestration/docker-compose
- https://nodejs.org/ja/docs/guides/nodejs-docker-webapp/
- https://stackoverflow.com/questions/36637912/how-to-stop-running-node-in-docker