Post

ZappaでAPI gateway , LambdaをDockerイメージからデプロイする

Requirements Flask App Docker Image AWS Configureでシークレット登録

ZappaでFlaskのDocker ImageをLambda + API Gatewayでデプロイする方法を紹介します。

以下は僕が使用したDockerFileです

1
2
3
4
5
6
7
8
9
10
11
12
FROM amazon/aws-lambda-python:3.9
ARG FUNCTION_DIR="/var/task/"
COPY ./ ${FUNCTION_DIR}
RUN pip3 install flask
RUN pip3 install zappa
RUN pip install -r requirements.txt
RUN ZAPPA_HANDLER_PATH=$( \
    python -c "from zappa import handler; print (handler.__file__)" \
    ) \
    && echo $ZAPPA_HANDLER_PATH \
    && cp $ZAPPA_HANDLER_PATH ${FUNCTION_DIR}
CMD [ "handler.lambda_handler" ]

以下は使用したDocker-composeファイルです。

1
2
3
4
5
6
7
8
version: "3"
services:
  app:
    build: .
    ports:
      - "5000:5000"
    container_name: app
    working_dir: /app

app.pyです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)


@app.route('/')
def health():
    return 'OK'

...


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

デプロイする前に、zappaの設定ファイルをPythonファイルにする必要があります。(zappa設定ファイルはzappa initで生成することができ、簡単に編集することができます)

以下のコマンドでzappa_settings.jsonからpyファイルへ変換をします。

1
$ zappa save-python-settings-file {profile name} 

次に、AWS上にDockerイメージのレポジトリを作ります。ECRというサービスで管理することができます。(事前にecrの権限を与えてください。)

1
$ aws ecr create-repository --repository-name {repository-name}

レスポンスとして以下のJsonが出力されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{                                                                                                                                                                                 
    "repository": {
        "repositoryArn": ...,
        "registryId": ...,
        "repositoryName": ...,
        "repositoryUri": ...,
        "createdAt": "2023-12-02T20:46:18+09:00",
        "imageTagMutability": "MUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": false
        },
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        }
    }
}

ここで、repositoryUriを記録しておいてください。

次に、生成されたECR レポジトリにログインをします。

1
2
$ aws ecr get-login-password | docker login --username AWS 
 --password-stdin {repositoryUri}

ログインに成功したと出力されたら、現在のDocker Imageの tagを変更します。

1
$ docker tag {nowImageName} {repositoryUri}

次に、AWS上のレポジトリにpushをします。

1
$ docker push {repositoryUri}

pushが完了したら、zappaでイメージのデプロイを行います。

1
$ zappa deploy {profileName} -d {repositoryUri}:latest

これでデプロイできると思います。関数の更新は以下のコマンドで行います。

1
$ zappa update {profileName} -d {repositoryUri}:latest

もし以下のエラーが出たら、Flaskがちゃんと動作していないのでPythonコードをチェックしてみてください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ zappa update dev -d  [docker image url]

Calling update for stage dev..
Updating Lambda function code..
Waiting for lambda function [othello-api-dev] to be updated...
Updating Lambda function configuration..
Uploading othello-api-dev-template-1701515222.json (1.6KiB)..
100%|██████████████████████████████████████| 1.64k/1.64k [00:00<00:00, 28.3kB/s]
Deploying API Gateway..
Scheduling..
Unscheduled othello-api-dev-zappa-keep-warm-handler.keep_warm_callback.
Scheduled othello-api-dev-zappa-keep-warm-handler.keep_warm_callback with expression rate(4 minutes)!
Waiting for lambda function [othello-api-dev] to be updated...
Error: Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 502 response code.

関数作成失敗時

This post is licensed under CC BY 4.0 by the author.