2
2

More than 1 year has passed since last update.

ServerlessFramework を使い AWS Lambda Python のローカル開発

Posted at

Serverless Frameworkを使い AWS Lambda のPython用のローカル環境の作成と実行について記載した内容です
AWSマネジメントコンソールでプログラミング・コーディングするのでなく、ツールを使い開発者体験をよくしていきたい。

はじめに

  • Dockerで Serverless Framework 環境構築 の記事のようなことをします
  • https://qiita.com/ssugimoto/items/ebe5b2ab5efbb6c6e541 の記事はdev container(旧、リモートコンテナ)を使った場合として位置づけていますので、今回の内容とは異なります
  • Developing inside a Containerではなく(.devcontainer/devcontainer.jsonを使わずに)、dockerコンテナとして、docker composeでdockerfileを使った場合の開発を試していきます。
  • 個人的にはVS Codeのdev containerを使うことは多いけど、自身でdockerコマンドやdocker composeコマンドを使った場合の方が少ない

VS Codeにインストールした拡張機能

  • SSH接続しコンテナ内のファイルを直接編集することができ、コンテナ内でコマンド実行もできます
  • それぞれの関係がよくわからないのですが、ひとまず3つ入れておけばなんとかなる
  • Dev Containers
  • Remote explorer
  • Remote Development

1.ローカル開発環境準備

サンプルソース

  • GitHub https://github.com/ssugimoto/serverless-framework-python-example2
    • README_ja.md と この記事を見てください
  • Dockerfile
    • そのまま利用しても良いです
    • nodeのバージョンを変えて良いです
    • PythonはFromのベースイメージで変更可能です
  • Windows 11 / docker desktop / Docker Compose V2 / WSL2

ディレクトリ・ファイル構成

│  .env
│  .gitignore
│  compose.yml
│  README.md
├─app
└─serverless
        Dockerfile

2. docker コマンド実行し、コンテナビルドとコンテナ実行

2-1. 環境変数用 .env ファイルを作成し、AWSのIMAユーザー情報を記載する。 gitignoreファイルにしておくことも忘れずに。

#AWS keys
AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY=YYYYYYYYYYYYYYY
  • .env や他ファイル
cd C:\usr\python\sls-docker-20230903
>tree /f

│  .env
│  .gitignore
│  compose.yml
│  README_ja.md
├─app
└─serverless
        Dockerfile

2-2. docker composeを実行

2-2-1. compose.yml ファイルのある場所に移動
2-2-2. docker compose のコマンドを実行、今回はバックグラウンド実行のため -d を付けて実行。

docker compose up -d

2-2-3. 実行例
serverless Errorの要因は、調査中です、 Dockerfileの image: serverlessをコメントにすると表示されなくなる

C:\usr\python\sls-docker-20230903>docker compose up -d
[+] Running 0/1
 - serverless Error                                                                                                2.5s
[+] Building 2.0s (15/15) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 1.66kB                                                                             0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/python:3.11                                                     1.9s
 => [auth] library/python:pull token for registry-1.docker.io                                                      0.0s
 => [ 1/10] FROM docker.io/library/python:3.11@sha256:02808bfd640d6fd360c30abc4261ad91aacacd9494f9ba4e5dcb0b86506  0.0s
 => CACHED [ 2/10] RUN apt-get update -y && apt-get upgrade -y                                                     0.0s
 => CACHED [ 3/10] RUN wget https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip   && unzip awscli-exe-linux-  0.0s
 => CACHED [ 4/10] RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash   && . $HO  0.0s
 => CACHED [ 5/10] RUN node -v                                                                                     0.0s
 => CACHED [ 6/10] RUN npm -v                                                                                      0.0s
 => CACHED [ 7/10] RUN pip install boto3                                                                           0.0s
 => CACHED [ 8/10] RUN sls config credentials --provider aws --key XXX --secret XXX  0.0s
 => CACHED [ 9/10] RUN mkdir -p /app                                                                               0.0s
 => CACHED [10/10] WORKDIR /app/app                                                                                0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:251085204bde8ed12576e25079168e9efe7977bde4096922e2c55d3664ae9d83                       0.0s
 => => naming to docker.io/library/serverless                                                                      0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
[+] Running 2/2
 - Network sls-docker-20230903_default  Created                                                                    0.0s
 - Container sls-python3-aws-lambda1    Started                                                                    0.4s
  • docker psで状況確認
C:\usr\python\sls-docker-20230903>docker ps
CONTAINER ID   IMAGE        COMMAND     CREATED         STATUS         PORTS     NAMES
34a9fb347401   serverless   "python3"   3 minutes ago   Up 3 minutes             sls-python3-aws-lambda1
  • ps コンテナ表示
C:\usr\python\sls-docker-20230903>docker compose ps
NAME                      COMMAND             SERVICE             STATUS              PORTS
sls-python3-aws-lambda1   "python3"           serverless          running
  • images Dockerイメージ表示
C:\usr\python\sls-docker-20230903>docker compose images
Container                 Repository          Tag                 Image Id            Size
sls-python3-aws-lambda1   serverless          latest              251085204bde        1.91GB

3. 起動したコンテナに対してVS Codeから接続する

3-1. VS Codeの拡張機能の 「Remote Explorer」を押して

image.png

3-2. コンテナ内に接続

DEv Containersの階層の下にある
「 →のボタン Attach In Current Window , + のボタン Attach In New Window」を押す
なお、Other Containersの階層の下には表示されない

3-3. VS Codeeでコンテナを開いた後のイメージ

image.png

左下で 「>< Container serverless(sls-python3-aws-lambda1)」・・・compose.ymlの中にある「container_name: sls-python3-aws-lambda1」の表示がされる

3-4. コンテナの中に入る

  • 3-4-1. ツールバーの 「Terminal -> New Terminal 」を押して
  • 3-4-2. コマンドでPATH等を確認する
root@34a9fb347401:/app# node -v
v18.17.1

root@34a9fb347401:/app# sls -v
Framework Core: 3.34.0
Plugin: 6.2.3
SDK: 4.3.2

root@34a9fb347401:/app# npm -v
9.6.7

root@34a9fb347401:/app# ls -l
total 12
-rwxrwxrwx 1 root root  910 Sep  7 03:06 README_ja.md
drwxrwxrwx 1 root root 4096 Sep  6 11:58 app
-rwxrwxrwx 1 root root  494 Sep  6 11:38 compose.yml
drwxrwxrwx 1 root root 4096 Sep  3 11:15 serverless
  • ターミナルの表示例
    image.png

4. Serveless Frameworkを使い、AWS Lambda Pythonのひな形作成

4-1 コマンド実行

cd /app/app
serverless create --template aws-python3 --name lambda-sample --path ./lambda-sample

実行例

root@c1ae820b8cb2:/app/app# serverless create --template aws-python3 --name lambda-sample --path ./lambda-sample

✔ Project successfully created in "./lambda-sample" from "aws-python3" template (3s)

作成されたファイル一覧

.
│  .gitignore
│  handler.py
│  serverless.yml

4-2. 作成されたファイルの修正

serverless.yml
  • Python のランタイムバージョンを3.9から3.11に変更
  • リージョンを追加 (aws-profileや引数で指定しても可)
    引数だと、serverless deploy --stage production --region ap-northeast-1 のような使い方

4-3. AWSにデプロイ(Lambda リソース作成)

sls deploy

実行例

root@c1ae820b8cb2:/app/app/lambda-sample# sls deploy

Deploying lambda-sample to stage dev (us-east-1)

✔ Service deployed to stack lambda-sample-dev (92s)

functions:
  hello: lambda-sample-dev-hello (389 B)

Need a faster logging experience than CloudWatch? Try our Dev Mode in Console: run "serverless dev"

5. 少し工夫等

5-1 serverless.yml 変更

  • serverless.ymlでS3バケット指定やstage、memorySize、timeout等を調整
  • 事前に、S3バケットをAWSマネジメントコンソール等を使って作成しておき、そのS3バケットを使うようにする
  • S3バケットは、serverless frameworkが使うstate情報(cloudformationやLambdaのソースzipファイル)を保持します
  • 変更例
serverless.yml

custom:
  defaultStage: dev

provider:
  name: aws
  runtime: python3.11
  region: us-east-1
  stage: ${opt:stage, self:custom.defaultStage}  #stageの指定を引数と指定無しデフォルト
  deploymentBucket:
    name: sls-lambda-sample-dev-randomabcd12345 # your S3 bucket, Create in advance.
    maxPreviousDeploymentArtifacts: 10


functions:
  hello:
    handler: handler.hello
    memorySize: 128    # default 1024MB
    timeout: 30        # AWS Lambda 15minute.=60*15=900sec

5-2. Lambda functionの実行

実行コマンド:

serverless invoke [local] --function functionName

5-2-1. AWS クラウド側のLambdaを実行する

sls invoke --function hello

実行例

# cd /app/app/lambda-sample
# sls invoke --function hello
{
    "statusCode": 200,
    "body": "{\"message\": \"Go Serverless v1.0! Your function executed successfully!\", \"input\": {}}"
}

5-2-2. ローカル側のLambdaを実行する

クラウド側で実行しているかローカル実行なのか違いがわからないので、handler.pyのレスポンスとなるbodyのmessageを変えてみます

def hello(event, context):
    body = {
        "first_message": "Hello World!",
        "message": "Go Serverless v1.0! Your function executed successfully!",
        "input": event
    }

...

実行例


# cd /app/app/lambda-sample
# sls invoke local --function hello
{
    "statusCode": 200,
    "body": "{\"first_message\": \"Hello World!\", \"message\": \"Go Serverless v1.0! Your function executed successfully!\", \"input\": {}}"
}

6. 2回目以降の対応、コンテナの起動、停止、リビルド

流れとしては
コンテナをdocker composeコマンドを使い実行 -> VS Codeを起動し、File -> Open Recent で Container... のものを選択する。すると、VS Codeのターミナルはコンテナの中になり、左のExplorer(ツリー)は compose.yml ファイルのあるディレクトリになる

docker コンテナを停止させるには?

  • docker desktop のGUI画面で 停止■ボタンを押す
  • docker compose stop を実行する

docker コンテナを起動させるには?

  • docker desktop のGUI画面で 開始再生▶ボタンを押す
  • docker compose start を実行する
    なお、docker compose up -d でも、Dockefileに変更なければ、start相当になります

dockerコンテナを消す(削除)は?

docker-compose down

さらに 停止&削除(コンテナ・ネットワーク・イメージ)

docker-compose down --rmi all

  • 下記のコマンドだけではコンテナのビルドできない場合が多々あります、ビルド済イメージを消さないといけない
docker-compose up --build

docker-compose up -d --build

7. .py だけでなく pip ライブラリを使う場合

サンプル

参考ドキュメント

作成方法

7-1. Pythonテンプレートを利用しひな形から作成

cd /app/app
serverless create --template aws-python3 --name lambda-lib-sample --path ./lambda-lib-sample

7-2. severless frameworkのpluginをインストール

cd lambda-lib-sample
sls plugin install -n serverless-python-requirements

serverless.yml に以下が追加されます、node_modulesディレクトリも作成され package.json、package-lock.jsonファイルも作成されます

serverless.yml
plugins:
  - serverless-python-requirements

7-3. requirements.txt を作成

必要なライブラリとバージョンを指定する

boto3>=1.28.43

7-4. パッケージングのための調整

serverless.yml

package:
  individually: false
  patterns:
    - '!**/*'
    - handler.py

7-5. サンプルソースでは Lambda function一覧を取得するので、LambdaのIAMロールに権限を付与

serverless.yml
  iam:
    role:
      statements:
        - Effect: "Allow"
          Action:
            - "lambda:List*"
          Resource: "*"

7-6. sls packageで試し

sls package

7-7. sls deploy でデプロイ

sls deploy

7-8. sls invokeで AWS Lambdaの実行

sls invoke --function hello

余談

dev containersの説明

The Visual Studio Code Dev Containers extension lets you use a container as a full-featured development environment. It allows you to open any folder inside (or mounted into) a container and take advantage of Visual Studio Code's full feature set. A devcontainer.json file in your project tells VS Code how to access (or create) a development container with a well-defined tool and runtime stack. This container can be used to run an application or to separate tools, libraries, or runtimes needed for working with a codebase.

Workspace files are mounted from the local file system or copied or cloned into the container. Extensions are installed and run inside the container, where they have full access to the tools, platform, and file system. This means that you can seamlessly switch your entire development environment just by connecting to a different container.

日本語訳

Visual Studio Code Dev Containers 拡張機能を使用すると、コンテナをフル機能の開発環境として使用できます。これにより、コンテナ内の(またはコンテナにマウントされた)任意のフォルダを開き、Visual Studio Codeの全機能を利用できるようになります。プロジェクト内のdevcontainer.jsonファイルは、明確に定義されたツールとランタイムスタックを持つ開発コンテナへのアクセス(または作成)方法をVS Codeに伝えます。このコンテナは、アプリケーションを実行したり、コードベースの作業に必要なツール、ライブラリ、ランタイムを分離したりするために使用できます。

ワークスペースのファイルは、ローカルのファイルシステムからマウントされるか、コンテナにコピーまたはクローンされる。拡張機能はコンテナ内にインストールされて実行され、ツール、プラットフォーム、ファイルシステムにフルアクセスできる。つまり、別のコンテナに接続するだけで、開発環境全体をシームレスに切り替えることができる。

dev containers(リモートコンテナ)の登場で、ローカルでNodeやPythonを動かすことが極端に減りました。ただ、CPUは8コア以上、メモリは32GB以上(64GBが理想)

他のツールは?

  • 運用で必要なLambda等でなく、アプリケーションとして動かすならばCI/CDまで構築できたら良い
  • 今回は、Serverless Frameworkを使っていますが、AWS Toolkit や AWS SAMとSAM cliとCDKを使う場合もあります
  • dockerコンテナでServerless FrameworkとPythonを動かすことで個人の環境に依存しない、ローカル環境を汚さない、バージョン違いでの無用なトラブル防止に役立つ
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2