読者です 読者をやめる 読者になる 読者になる

歩いたら休め

If the implementation is easy to explain, it may be a good idea.

【Python3.6】AWS Lambdaを再現するDocker Imageのdocker-lambdaを使ってみた

この間AWS LambdaでPython 3.6がサポートされたので、レンタルサーバーで動かしているTwitterの自動投稿やクローラーを移行しようと画策しています。

AWS LambdaがPython3.6に対応したので使ってみた | Developers.IO

外部ライブラリ(twitterライブラリやBeautifulSoupなど)を利用使いたいので、zipで固めてデプロイする方法でいきたいのですが、いろいろ面倒そうなのでまずはその辺の煩雑な作業を自動化する手段でやってみました。

いろいろ調べていくうちに、以下の記事に紹介されている、「手元の環境で擬似的にLambdaを実行する」というDockerイメージが良さそうだったので使ってみます。

AWS Lambdaの開発環境を構築~docker-lambdaの紹介~ – クリエイティブ - ブログ - 株式会社テレビ朝日メディアプレックス

今回は Lambdaのデバッグ効率を上げるdocker-lambdaの設定手順を紹介します。

名前からイメージ出来る通り、Dockerで疑似的にLambdaを実行するという物になります。

github.com

ただし、Docker Imageが2GB弱ほどあるので、多少ハードディスクの容量は食ってしまうので、もしローカル環境で使うならば注意が必要かもしれません。

私はMac OS Xを利用しているので、公式サイトの"Docker for Mac"からダウンロードしました。

実は未だにちゃんとDockerを使ったことが無かったのですが、次のサイトを参考に簡単に勉強すれば、問題なく使うことができました。

www.atmarkit.co.jp

docker-lambdaを試しに実行する

lambda_function.pyという名前で現在のこのようなファイルを用意します。

def lambda_handler(event, context):   
    print("value1 = " + event['key1'])
    return event['key1']

公式のExampleにもある通り、引数にeventの値となるjsonを渡して実行します。

$ ls
lambda_function.py
$ docker run -v "$PWD":/var/task lambci/lambda:python3.6 lambda_function.lambda_handler '{"key1": "key2"}'
START RequestId: bcc19516-283b-485d-b728-69497756be19 Version: $LATEST
value1 = key2
END RequestId: bcc19516-283b-485d-b728-69497756be19
REPORT RequestId: bcc19516-283b-485d-b728-69497756be19 Duration: 32 ms Billed Duration: 132.0 ms Memory Size: 1536 MB Max Memory Used: 18 MB
"key2"

docker-lambdaでデプロイパッケージを作成する

次は、デプロイパッケージをdockerを使って作成します。

ローカルの環境(Mac OS X)でも同じことはできるのですが、特にPure Pythonでないライブラリを利用する際にエラーが出てしまうそうなので、できるだけ実際のAWSに近い環境でライブラリが用意できるので変なエラーに詰まることが少なくなることが期待されます。

docs.aws.amazon.com

Lambda 関数を作成するには、最初に Lambda 関数デプロイパッケージ (コードと依存関係で構成される .zip ファイル) を作成します。

以下の記事と、docker-lambdaリポジトリの「Create your own Docker image for finer control:」の項目を参考にして簡単にPython3.6をビルドできるdocker imageを作ります。

qiita.com

デプロイ用のDocker Imageを用意する

以下のようなDockerfileを用意します。

FROM lambci/lambda:build-python3.6

ENV AWS_DEFAULT_REGION us-east-1

ADD . .

CMD pip3 install -r requirements.txt -t /var/task && \
  zip -9 deploy_package.zip lambda_function.py && \
  zip -r9 deploy_package.zip *

mylambdaという名前でイメージを作ります。

docker build -t mylambda .

コードを用意する

作業ディレクトリで、lambda_function.pyとrequirements.txtを用意します(というか、この名前でファイルが存在していることを前提にDockerfileを書いています)。

$ ls
lambda_function.py requirements.txt

ひとまず、著名な外部ライブラリであるrequestsを使ったコードを書いてみます。

ひとまず、lambda_function.pyという名前で、こちらの記事で紹介されているグローバルIPを確認するAPIを呼び出しています。

import requests


def lambda_handler(event, context):
    res = requests.get('http://httpbin.org/ip')
    return res.json()

requirements.txtはこのような内容です。具体的なバージョンは特に指定していません。

requests

Dockerの環境内でzipで固める

次のコードを実行することで、Dockerfileの"RUN"の項目で指定されているシェルスクリプトが動き、deploy_package.zipが吐き出されます。

docker run -v "$PWD":/var/task mylambda

このdeploy_package.zipをアップロードすると、awscli等でアップロードすればLambda上で動かすことができます。

f:id:takeshi0406:20170506144610p:plain

まとめ

docker-lambdaを使ってAWS Lambdaの開発が便利になることを簡単に確認しました。

また、zipファイルとdevを同じディレクトリに保存しているので、何度も試行錯誤を行う際は微妙かもしれないので、適宜書き換えつつ利用しようと思います。

手軽に環境を捨てられるのもDockerの利点だと思うので。