Serverless Frameworkを使ってAWS Lambdaにdeployできる環境を作る

# 概要
* [serverless framework](https://serverless.com/framework/docs/providers/aws/guide/intro/) を使ってAWS AWS Lambdaにdeployする方法
* 外部ライブラリも一緒にdeployできます。
* docker-lambda を使ってpipインストール

# 環境
* macOS 10.13.6
* Docker 18.03.1-ce
* npm 5.6.0
* python 3.6.5
* アクセス権限 AdministratorAccess を付与されたIAMユーザー
* awscliがインストールされている（ `sudo pip install awscli
` ）

# 手順
## インストール
* serverlessをインストール

```
npm install --save serverless
```
* モジュールを一緒にdeployするためのプラグイン[serverless-python-requirements](https://github.com/UnitedIncome/serverless-python-requirements)をインストール

```
npm install --save serverless-python-requirements
```

* localでlambdaスクリプトを実行するためのライブラリをインストール

```
pip install python-lambda-local
```

* （ついでに）今回のdeployのテストで使うライブラリ[python-levenshtein](https://github.com/ztane/python-Levenshtein)もインストールしておきます。

```
pip install python-levenshtein
```
## 設定
### awsのプロファイルを設定する
[AWS CLI の設定](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-getting-started.html)を参考にして設定します。

以下のような感じ。

```
aws configure --profile 用意したユーザー名

AWS Access Key ID [None]: アクセスキー
AWS Secret Access Key [None]: シークレットアクセスキー
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

### python3用のserverlessのテンプレートを出力する

lambdaのファイルを管理するフォルダを作成し、そこの中に移動して、以下のコマンドを打ちます

```
serverless create --template aws-python3
```

.gitignore, handler.py, serverless.ymlが作成されます。

## deploy設定をする
`serverless.yml` を以下のように編集します（コメントは削除しました。）。

```serverless.yml
service: aws-python3

provider:
  name: aws
  runtime: python3.6
  region: ap-northeast-1

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    dockerizePip: true

functions:
  sample-func:
    handler: handler.main
```


docker-lambdaでコンパイルされたライブラリを使うための設定は、以下の箇所です。（[参考](https://github.com/UnitedIncome/serverless-python-requirements#cross-compiling)）。

```
custom:
  pythonRequirements:
    dockerizePip: true
```

## サンプルコードを作成する

二つの文字列のLevenshtein距離を求めるコードをです。


```handler.py
import json
import Levenshtein


def main(event, context):
    print(Levenshtein.distance("東京都", "東海道"))
```

* 必要なライブラリを `requirements.txt` に記述する

```requirements.txt
python-levenshtein
```

## 動作確認
### ローカルで試す
python-lambda-localをつかってローカルで動作確認します。引数用の `event.json` をつくります。実際は使わないので、空のjsonです。

```event.json
{}
```

実行します。

```
python-lambda-local -f main handler.py event.json

[root - INFO - 2018-07-22 11:36:43,446] Event: {}
[root - INFO - 2018-07-22 11:36:43,447] START RequestId: c2f1d96c-fed5-48c9-bb98-2ea9a541f6d3
2
[root - INFO - 2018-07-22 11:36:43,448] END RequestId: c2f1d96c-fed5-48c9-bb98-2ea9a541f6d3
[root - INFO - 2018-07-22 11:36:43,448] RESULT:
None
[root - INFO - 2018-07-22 11:36:43,449] REPORT RequestId: c2f1d96c-fed5-48c9-bb98-2ea9a541f6d3  Duration: 0.98 ms
```

計算されてます。

### deployする
* aws-profileには先に用意したユーザー名を入力して下さい。

* 下記を実行して下さい。

```
serverless deploy --aws-profile 用意したユーザー名 --verbose
```

下記の様なログが出力されて、ライブラリとともにローカルのコードがS3経由でLambdaにdeployされます。

```
Serverless: Installing requirements of requirements.txt in .serverless...
Serverless: Docker Image: lambci/lambda:build-python3.6
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Injecting required Python packages to package...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (399.66 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - aws-python3-dev
CloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::Function - SampleDashfuncLambdaFunction
CloudFormation - UPDATE_COMPLETE - AWS::Lambda::Function - SampleDashfuncLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - SampleDashfuncLambdaVersion6OU7Kc3zila3ZAax4gvx0
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - SampleDashfuncLambdaVersion6OU7Kc3zila3ZAax4gvx0
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Version - SampleDashfuncLambdaVersion6OU7Kc3zila3ZAax4gvx0
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - aws-python3-dev
CloudFormation - DELETE_SKIPPED - AWS::Lambda::Version - SampleDashfuncLambdaVersionvDNqLnGSqO3Kpr8t0M
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - aws-python3-dev
Serverless: Stack update finished...
Service Information
service: aws-python3
stage: dev
region: ap-northeast-1
stack: aws-python3-dev
api keys:
  None
endpoints:
  None
functions:
  sample-func: aws-python3-dev-sample-func

Stack Outputs
SampleDashfuncLambdaFunctionQualifiedArn: arn:aws:lambda:ap-northeast-1:07898663:function:aws-python3-dev-sample-func:10
ServerlessDeploymentBucketName: aws-python3-dev-serverlessdeploymentbucket-19aaa

```

### deploy確認
* AWSのLambdaにアクセスするとライブラリと共にdeployされていることが確認されます。

[![Image from Gyazo](https://i.gyazo.com/b0f9f0a6fc4f65ecead31348531107ac.png)](https://gyazo.com/b0f9f0a6fc4f65ecead31348531107ac)

以上、