DjangoをLambdaを使ってサーバレスにデプロイする

DjangoをAWS Lambdaにデプロイできました。Serverless Frameworkを使うと簡単です。
URLとレポジトリはこちらです。
[https://django-sls-helloworld.umihi.co/](https://django-sls-helloworld.umihi.co/)
[https://github.com/umihico/django-sls-helloworld](https://github.com/umihico/django-sls-helloworld)

2021/05/26追記
Laravel,Nuxtバージョンもあります。

- [NuxtをコンテナにしてLambdaでデプロイするのが超簡単になった2021年](https://qiita.com/umihico/items/fb8733c6cba1e195181d)
- [DjangoをLambdaを使ってサーバレスにデプロイする](https://qiita.com/umihico/items/4534e1f84e8de5a62db5)

slsのデフォルトプロジェクトを作成し、[f1a13ba](https://github.com/umihico/django-sls-helloworld/commit/f1a13ba)
動作確認したらカスタムドメインをプラグインをインストールします。[0970afe](https://github.com/umihico/django-sls-helloworld/commit/0970afe1228ceeb646042c0c2a1012a2c44646a3)
API GatewayはURL末端につくstage名を外せず、djangoのルーティングと相性が悪いようで、カスタムドメインを先に整えました。

```bash
$ serverless create --template aws-python3 --path django-sls-helloworld # プロジェクト作成 
$ cd django-sls-helloworld
$ serverless deploy #　一度デプロイ
$ serverless invoke -f hello # 正常に動くかテスト
{
    "statusCode": 200,
    "body": "{\"message\": \"Go Serverless v1.0! Your function executed successfully!\", \"input\": {}}"
}
$ sls plugin install -n serverless-domain-manager #　ドメイン設定のためのプラグインインストール
```

serverless.ymlを編集します。[603753b](https://github.com/umihico/django-sls-helloworld/commit/603753bfd5f05c6c65ae02ea85bfb76f2737d123)

```diff:serverless.yml


+ custom:
+   customDomain:
+     domainName: django-sls-helloworld.umihi.co
+     certificateName: umihi.co
+     basePath: ''
+     stage: ${opt:stage, self:provider.stage}
+     createRoute53Record: true
+     endpointType: 'edge'
+     securityPolicy: tls_1_2

provider:
  name: aws
  runtime: python3.8
```


```bash
$ sls create_domain
# 最大４０分かかると言われるが、次のデプロイコマンドはすぐにできる。ただドメイン適用に時間がかかるだけ。
$ sls deploy
```

これで、カスタムドメイン設定されたWEBページが完成しました。次にDjangoに必要なライブラリをインストールします。[80e8f1b](https://github.com/umihico/django-sls-helloworld/commit/80e8f1b3096b83ab394d5edaabb10915d9b51460)

```bash
$ sls plugin install -n serverless-python-requirements
```

以下のファイルを追加し、不要ですがインポートされてるかテストのため、handler.pyも編集しました。[ec47570](https://github.com/umihico/django-sls-helloworld/commit/ec475707787aaad236c1c835ea8a6d6869e29c16)

```python:requirements.py
import os
import sys

requirements = os.path.join(
    os.path.split(__file__)[0],
    '.requirements',
)

if requirements not in sys.path:
    sys.path.append(requirements)
```


```text:requirements.txt
Django
Werkzeug
PyMySQL
```

```diff:handler.py
import json
+ import requirements

def hello(event, context):
+     # testing import libraries
+     import django
+     import werkzeug
+     import pymysql
    body = {
        "message": "Go Serverless v1.0! Your function executed successfully!",
```

デプロイし、`serverless invoke -f hello`が正常であれば、importは成功です。
次に、Djangoのプロジェクトを作成します。[930a0c2](https://github.com/umihico/django-sls-helloworld/commit/930a0c27e2c0dfb4b30b691708309c9b3f7e77f6)
そして、サーバレスライブラリ用のWSGIプラグインをインストールします。[52386e4](https://github.com/umihico/django-sls-helloworld/commit/52386e4dca8e9b203d87c4a71da5a1a3fc55f689)

```bash
$ django-admin startproject django_sls_helloworld .
$ sls plugin install -n serverless-wsgi
```

最後に、
MySQLdbの代わりにPyMySQLをインストールする修正と、その際に指摘されるバージョン違いを修正し、[30361dd](https://github.com/umihico/django-sls-helloworld/commit/30361ddb18ab58d50a698e13c2259f23ce7e0c00)
ALLOWED_HOSTに設定したドメインを名を加え、[1966857](https://github.com/umihico/django-sls-helloworld/commit/1966857aa6a5addc81b153281b27e36e13eb01a2)
LambdaがWSGIを参照するように振り分けます。[1dce3d3](https://github.com/umihico/django-sls-helloworld/commit/1dce3d3892b9820f7b6c90ee9749ab36810554a0)

```diff:django_sls_helloworld/settings.py
import os
+ import pymysql
+ 
+ pymysql.version_info = (1, 4, 2, "final", 0)
+ pymysql.install_as_MySQLdb()
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)

省略

DATABASES = {
    'default': {
-         'ENGINE': 'django.db.backends.sqlite3',
-         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+         'ENGINE': 'django.db.backends.mysql',
+         'NAME': 'djangodemo',
    }
}

省略

- ALLOWED_HOSTS = []
+ ALLOWED_HOSTS = ["django-sls-helloworld.umihi.co"]
```

```diff:serveless.yml
  endpointType: 'edge'
  securityPolicy: tls_1_2
+ wsgi:
+   app: django_sls_helloworld.wsgi.application
+   packRequirements: false

省略

functions:
  hello:
-     handler: handler.hello
+     handler: wsgi_handler.handler
#    The following are a few example events you can configure
```

デプロイしてお馴染みの画面がカスタムドメイン先でも現れました。以上です。
ちなみに使い捨てプロジェクトなので、`DEBUG=True`でデプロイし、かつ`SECRET_KEY`もGithubにあげてますが、実運用ではタブーなのでご注意ください。

![スクリーンショット 2020-06-20 11.14.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256466/6a576e11-5b7a-bec2-d172-43466dc84ed8.png)