13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

docker-lambda + minioで環境構築

Last updated at Posted at 2019-12-30

AWS S3互換であるminioと、lamda function開発用のdocker imageであるdocker-lambdaを使って、ローカルで開発環境を作ろうというお話です。

Minio

MinioはAWS S3互換のObject Strageで、ローカルにS3環境を作ることができます。
公式ドキュメントも用意されており、Dockerがあれば手軽にはじめられます。

起動するとこんな感じです。
Screenshot from 2019-12-26 18-45-04.png

Screenshot from 2019-12-26 18-45-41.png

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>

以下のファイルを適当なディレクトリで作成。

function.py
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をしていする。

function.py
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を立てたコンソールで結果が見えるはずです。

参考

13
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?