Help us understand the problem. What is going on with this article?

AWS Lambda x Pythonでのローカル開発環境の再現について

AWS Lambdaを使ってなにかを作るとき(Python)についての考察です。

■ Overview

  • AWS LambdaとPythonを使って開発するときにローカル環境をどう作っていくかについて。
  • AWS Lambdaをローカルで再現する手段

■ 問題点

  • AWS LambdaとPythonで開発する際に、モジュールなどのインポートする際に依存関係があるとLambdaのGUI上ではそのまま実行できないため、一度他の場所で依存関係をインストールしてzip化してアップロードするケースが多い。
  • スクリーンショット 2018-10-30 17.18.41.png

ただ、その都度変更があるためにzip化してアップロードするのは大変。すぐに反映を確認できないと開発効率がさがってしまう。
image.png

■ 解決策

主に2つあります。

① EC2 or AmazonLinux for Dockerを使い開発する

Lambdaは、AmazonLinuxで動いているためローカルPCでローカル開発環境を準備して開発し、それをzip化アップロードしても失敗するケースがあります。
なので、他に環境を用意する必要があります。方法は2つあり
- EC2インスタンスを立ててその中で開発する。
- AmazonLinuxの公式Dockerイメージの中で開発を行う。

image.png

前者のEC2を立てるのは、あまりスマートではなくコストもかかるのでおすすめできません。
AmazonLinuxの公式Dockerについては、その中で開発を行え常にクリーンな環境を保てます。

$ docker pull amazonlinux

https://hub.docker.com/_/amazonlinux/

② docker-lambdaを利用する

個人的には、こちらが一番良いかと思います。

https://github.com/lambci/docker-lambda

docker-lambdaを文字通り、AWS Lambdaの環境を再現したDockerイメージです。
これを使い、Dockerfileをビルドしてアップロードすればかなりよい環境ができあがります。AmazonLinuxのDockerイメージでもよいのですが、こちらのdocker-lambdaのほうがはじめからLambdaを再現できているので余計なことをせずに簡単です。
image.png

■ docker-lambdaを触ってみる

簡単ではありますが、サンプルをbuildするまで行ってみます。

まずは、DockerfileをビルドするのではなくCLIからイメージをrunして動作確認してみます。

公式のlambci/docker-lambdaリポジトリを参考にしていきます。

lambda_function.pyを用意する。

AWS Lambdaではデフォールトでlambda_function.pyのlambda_handlerを呼び出すようになっているので今回も従っていきます・

lambda_function.py
import json

def lambda_handler(event, context):
    return event

docker-lambdaを実行していきます。

$ docker run -v "$PWD":/var/task lambci/lambda:python3.6 lambda_function.lambda_handler '{"Hello":"World"}'
Unable to find image 'lambci/lambda:python3.6' locally
python3.6: Pulling from lambci/lambda
5be106c3813f: Pull complete 
e240967675e1: Pull complete 
4ec29390cd9b: Pull complete 
fc6ba7ddc407: Pull complete 
492c7fb9ab78: Pull complete 
Digest: sha256:6a5cddcf16942a7a3ddc209f140a8d4105a87ce95cd374ffc6d953dd0b593d01
Status: Downloaded newer image for lambci/lambda:python3.6
START RequestId: 3f39da27-a241-4fd2-ad77-e92ec63ffada Version: $LATEST
END RequestId: 3f39da27-a241-4fd2-ad77-e92ec63ffada
REPORT RequestId: 3f39da27-a241-4fd2-ad77-e92ec63ffada Duration: 12 ms Billed Duration: 100 ms Memory Size: 1536 MB Max Memory Used: 19 MB

{"Hello": "World"}

単純にJSONも文字列を渡して出力しているだけですが、無事に『{"Hello": "World"}』がでました。

ビルドイメージをDockerfileに書いていく。

では、ここでビルド用のDockerfileを書いていきます。
内容としては、上記のlambda_function.pyと依存関係をzip化し、デプロイパッケージを作成していきます。
デプロイパッケージの作成

ビルド準備として、requirements.txtというテキストを用意しそこに依存するインポート群を書いていきます。

requirements.txt
requests

再度、requestsモジュールを使ったlambda_function.pyを用意します。DMM.comにアクセスしてstatus_code : 200を返すスクリプトです。

lambda_function.py
import requests

def lambda_handler(event, context):
    res = requests.get('https://www.dmm.com/')
    return res.status_code 

では、ビルドしていきます。

Dockerfile
FROM lambci/lambda:build-python3.6
ENV AWS_DEFAULT_REGION ap-northeast-1

ADD . .

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

まずは、イメージを作成します。

$ docker build -t mylambda .
イメージ確認
$ docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mylambda            latest              14a0a97cd00a        5 minutes ago       1.8GB
lambci/lambda       build-python3.6     0f6150a9635c        7 days ago          1.8GB

ではZipに固めていきます。

build
$ docker run -v "$PWD":/var/task mylambda
Collecting requests (from -r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/f1/ca/10332a30cb25b627192b4ea272c351bce3ca1091e541245cccbace6051d8/requests-2.20.0-py2.py3-none-any.whl (60kB)

~中略~

結果として、以下のようなディレクト構造ができます。deploy_package.zipがアップロード対象のフォルダーです。

ls -a
.               certifi             deploy_package.zip      requests            urllib3-1.24.dist-info
..              certifi-2018.10.15.dist-info    idna                requests-2.20.0.dist-info
Dockerfile          chardet             idna-2.7.dist-info      requirements.txt
bin             chardet-3.0.4.dist-info     lambda_function.py      urllib3

結果
Lambda上で、deploy_package.zipをzipアップロードすると結果として200が返ってきており、正しく動作していることがわかります。
スクリーンショット 2018-10-30 18.25.13.png

基本的にアップロードをローカルで検証できたらで良くて、普段はコンテナ内や引数でpythonを実行して動作確認するのがよさそうです。

以上です。

i35_267
事業部長 / Product Owner 主にMediumでブログを書いています。 https://medium.com/i35-267 Resume https://github.com/i35-267/resume
https://medium.com/i35-267
dmmcom
総合エンタテイメントサイト「DMM.com」を運営。会員数は2,900万人を突破。動画配信、FX、英会話、ゲーム、太陽光発電、3Dプリンタなど40以上のサービスを展開。沖縄での水族館事業参入、ベルギーでのサッカークラブ経営など、様々な事業を手掛ける。また2018年より若手起業家の支援を強化、「DMM VENTURES」による出資や、M&Aなどを積極的に展開している。
https://dmm-corp.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした