Docker-lambdaを使ったAWS Lambdaのローカル開発

Lambdaを使って開発してみたいなーと思ったときに、デバッグをローカルの環境でするのにdocker-lambdaが便利だったのでメモ。

はじめに

docker-lambdaとは?

A sandboxed local environment that replicates the live AWS Lambda environment almost identically – including installed software and libraries, file structure and permissions, environment variables, context objects and behaviors – even the user and running process are the same.

lambci/lambda – Docker Hub

ソフトウェアやライブラリ、ファイル構造などのAWS Lambbdaの環境をローカルで再現してくれるDocker image。追加したライブラリとかも含めて.zipにまとめて、本番環境にアップロードするファイルなんかも簡単につくれます。

環境

  • Mac OS Catalina (10.15.4)
  • Docker version (19.03.8)
  • Python3.8 (の環境を試します)

Hello World!

適当なディレクトリを作成し、lambda_function.pyを作成

# lambda_function.py
def lambda_handler(event, context):
    return "Hello docker lambda world!"

Dockerで実行

docker run --rm \
-v "$PWD":/var/task:ro,delegated \
lambci/lambda:python3.8 \
lambda_function.lambda_handler
# 出力
START RequestId: 9c...73 Version: $LATEST
END RequestId: 9c...73
REPORT RequestId: 9c...73	Init Duration: 621.98 ms	Duration: 16.44 ms	Billed Duration: 100 ms	Memory Size: 1536 MB	Max Memory Used: 24 MB

"Hello docker lambda world!"

以上!一瞬で環境を構築して実行できました。

メモ

  • -v "$PWD":/var/task:ro,delegated
    カレントディレクトリをマウント、lambda_function.pyをDocker内部から使えるようにしてる。
  • lambci/lambda:python3.8はDocker イメージの指定
    lambci/lambda Tags – Docker Hub にあるタグを使って他の言語も対応

HTTPリクエストを受ける

docker run --rm \
-p 9001:9001 \
-e DOCKER_LAMBDA_WATCH=1 -e DOCKER_LAMBDA_STAY_OPEN=1 \
-v "$PWD":/var/task:ro,delegated \
lambci/lambda:python3.8 \
lambda_function.lambda_handler

Docker外部の新しいterminalから実行

curl -d '{}' http://localhost:9001/2015-03-31/functions/lambda/invocations
# 2015-03-31とは…? でもアクセスできる。。
# 出力
"Hello docker lambda world!"%

以上!!

メモ

  • docker内部でエンドポイントが9001で立ち上がる。
    -p 9001:9001
    でローカルマシンからでも接続できるようにポートをつなげてる。
  • DOCKER_LAMBDA_STAY_OPEN=1
    でURLによるアクセスができるようにするオプション。Dockerが起動したままになる。Ctrl+Cで終了。
  • -vでカレントディレクトリをマウントしているので、Dockerを止めずにプログラムを編集しても反映される。

ビルド方法

最終的に完成したプログラムは関連ファイルなど全部固めて.zipに圧縮してAWS Lambdaにアップロードする。その.zipファイルを作る方法

必要なもの

  • Dockerfile (ビルド用)
  • requirements.txt (ライブラリ一覧)
Dockerfile
FROM lambci/lambda:build-python3.8
ENV LANG C.UTF-8
ENV AWS_DEFAULT_REGION ap-northeast-1

ADD . .

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

必要なモジュールを書いていきます。改行区切りで書いていけばOK
(今回は必要ないけどrequestsモジュールを追加)

# requirements.txt
requests
ビルドするための環境構築

こちらはDockerfileに書いたとおりbuild-python3.8というビルド用イメージが使われます。ビルド専用のDockerコンテナが作成されます。

# ビルドをするための環境構築
docker build -t build-image-python3.8 .
ビルド

実際のビルドは以下のコマンドです。依存関係のモジュールのインストールやらをやってくれます。docker buildは1回のみの実行で、以下のdocker runだけビルドのたびに実行します。

# ビルド
docker run --rm -v "$PWD":/var/task build-image-python3.8

ビルドコマンドを実行すると依存関係で必要なモジュール類が全部カレントディレクトリに作成されます。今回だとrequestsのみをrequirements.txtに書きましたが、certifiやchardetといった依存モジュールもインストールされています。

出力されたファイルのうちdeploy_package.zipがライブラリも含めた圧縮ファイルで、これをアップロードすればLamda関数として利用することができる。

(ざっくり)Lambdaへのアップロード方法

AWS Lambda > 関数の作成 > 一から作成(適当に名前をつける & ランタイムをPython3.8に) > 関数の作成

関数の設定画面 Lambda > 関数 > (関数名) で 関数の設定画面より
関数コード > コードエントリタイプ=> .zipファイルをアップロード
より生成されたdeploy_package.zipをアップロード。

実際にURLでアクセスする際にはAPI Gatewayの設定が少し必要。
ついでに、デフォルトの実行時間が3秒となっており、Lambdaから他のサイトの情報をとってきたりすると簡単に時間オーバーしてしまうので、関数の設定ページの下の方、[基本設定]のタイムアウトを少し長めにしておくといいかもです。

開発環境で外部パッケージをつかう

いろいろなサイトを調べていて、deploy_package.zipにライブラリを追加する手順はわかりました。でも実際には手元でパッケージを含めて何度も試したものを最終的にdeploy_packageにまとめたいです。そんな時はどうするのか?

開発環境lambci/lambda:python3.8を実行する際に、カレントディレクトリをマウントしていました。そこで、カレントディレクトリに必要なパッケージがインストールされていれば問題ないので、本番環境のビルド(lambci/lambda:build-python3.8を使ったDockerfileのやつ)でビルド(docker run --rm -v "$PWD":/var/task build-image-python3.8)すると、必要なパッケージがカレントディレクトリにて構築されて、開発環境でも使えるようになります。

他にも、手元でpip install (パッケージ) -t ./とかすれば行けそうですが、、このpipはローカル環境のpipなので、いい感じにbuild-pythonの中でpip installできたほうがいいと思います。

gspreadインストール時エラー

Google スプレッドシート(Google Sheets)をpythonから扱うライブラリgspreadをインストールしようとしたらエラーがでました。

ERROR: awscli 1.18.50 has requirement rsa<=3.5.0,>=3.1.2, but you'll have rsa 4.0 which is incompatible.

どうやらgspreadに依存してrsaのバージョン4.0がインストールされるが、awscli 1.18.50(すでに入ってる?)はrsaのバージョン3.1.2〜3.5.0が欲しいらしいです。エラーとか言いながらもきちんと出力できているのでヨシッとするか、requirements.txtの最初にrsa == 3.4.2とか書いておくと回避できます。(大丈夫なのか…?

まとめ

Lambdaの開発環境がとても簡単に構築でき、さらにビルドパッケージまで作成できました。むっちゃ便利!

余談ですがgspreadのProject description
“Super simple Google Spreadsheets Python API.”
とだけ書かれていました。全然詳細じゃないけどSuper simple descriptionだなと。実際gspreadは非常にシンプルで使いやすいのでオススメです!

参考:

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください