0
2

Python Lambda - コンテナ上でのローカルデバッグ環境構築

Last updated at Posted at 2023-11-07

内容

CDKで実装した Python Lambda のローカルデバッグ環境構築する
Lambdaの実行環境と合わせるため、Lambdaと同環境のコンテナを用意し、
Remote Developmentでコンテナに入りデバッグを行う
本記事で一旦ここまでを実施する

以下は別記事で対応する

フォルダ構成

今回以下のようにLambdaごとに外部パッケージをインストールしているが、
Lambdaのサイズ上限も考慮すると、EFS上に外部パッケージをインストールしてLambdaにアタッチする(参考)ほうが良さそうなため、
後日試してみる予定
AWS CDK - EFS での Python Lambda パッケージ管理

 ├─ .devcontainer
 │     └─ devcontainer.json
 ├─ .vscode
 │     ├─ extensions.json 
 │     └─ settings.json
 │
 ├─ bin/
 │   └─ sample.ts
 │
 ├─ lib/
 │    │
 │    ├─ handlers/                           // Lambda実装
 │    │   │
 │    │   └─ sample-function/
 │    │        ├─ python/
 │    │        │     ├─ pandas/             // 外部パッケージ
 │    │        │     …
 │    │        │     └─ sample_function.py  // Lambda関数実装
 │    │        │
 │    │        └─ requirements.txt          // Lambdaに含める外部パッケージ指定
 │    │
 │    ├─ layers/                            // Layer実装
 │    │   │
 │    │   ├─ python/
 │    │   │     ├─ pytz/                    // 外部パッケージ
 │    │   │     …
 │    │   │     └─ common_layer.py          // layerに含める共通処理実装
 │    │   │
 │    │   └─ requirements.txt               // layerに含める外部パッケージ指定
 │    │
 │    └─ sample-stack.ts
 │
 ├─ test/
 │    │
 │    ├─ sample-function/
 │    │            └─ test.py               // lib/handlers/sample-function/python/sample_function.pyのテストコード
 │    │
 │    ├─ docker-compose.yml
 │    └─ Dockerfile-lambda-python           // Python Lambda実行用のコンテナDockerfile
 …
 │
 ├─ poetry.lock
 ├─ pyproject.toml
 │

テスト対象Lambda関数コード

lib/handlers/sample-function/python/sample_function.py
import os
from datetime import datetime
from pytz import timezone
from common_layer import print_message  # type: ignore | common layer package
import pandas as pd

test_env_value = os.getenv("TEST_ENV_VALUE")


def handler(event, context):
    print(f"event: {event}")  # イベント内容の確認
    print(f"test_env_value: {test_env_value}")  # 環境変数の確認

    print_message("test message 1")   # Layerを使った処理

    df = pd.DataFrame([["A", 170, 60], ["B", 160, 50], ["C", 165, 58]])  # 外部パッケージpandasを使った処理
    print(f"df: {df}")

    tokyo_dt = datetime.now(timezone("Asia/Tokyo"))

    return {"statusCode": 200, "body": tokyo_dt.strftime("%Y-%m-%d %H:%M:%S")}

テストコード

test/sample-function/test.py
import os
from common_layer import print_message

os.environ["TEST_ENV_VALUE"] = "test env value"  # 環境変数設定
import sample_function


def test_1():
    print_message("layer test")
    event = {"key1": "value1", "key2": "value2"}  # Lambda handlerの引数設定
    context = {}

    sample_function.handler(event, context)  # Lambda handlerの実行


test_1()

import パスの追加

テストコード test/sample-function/test.py から、
layer内の外部パッケージ + 共通処理、
Lambda内の外部パッケージ、handlerが実行できるように
pyproject.toml内 [tool.poetry] ブロックの packages でimportパスを追加する
sys.path.append("<path>") でimportパスを追加するのと同じ)

pyproject.toml
[tool.poetry]
name = "sample"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
readme = "README.md"
packages = [
    { from = "lib/layers/python", include = "*" },
    { from = "lib/handlers/sample-function/python", include = "*" },
]

[tool.poetry.dependencies]
python = "3.11.6"
boto3 = "^1.28.78"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Lambdaと同環境のimageにboto3はインストールされているが、
poetryのinterpreterを使用するため、boto3は必要

Python Lambda 実行用のコンテナ

Python11のLambdaイメージをベースに、必要なモジュールをインストールする

Dockerfile-lambda-python
FROM public.ecr.aws/lambda/python:3.11

RUN yum update -y
RUN yum install -y unzip tar gzip less
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && unzip awscliv2.zip && ./aws/install
RUN pip install poetry

CMD ["/bin/bash"]

docker-compose

ソースコード一式をコンテナ内の /lambda-python に同期する
クレデンシャルも同期する

docker-compose.yml
version: "3.8"
services:
  lambda:
    container_name: lambda-python
    build:
      context: .
      dockerfile: Dockerfile-lambda-python
    volumes:
      - ../:/lambda-python
      - ~/.aws:/root/.aws
    working_dir: /lambda-python

Remote Development でのデバッグ

以下のように .devcontainer/devcontainer.json を設定しているが必須ではない

.devcontainer/devcontainer.json
{
  "name": "lambda-python",
  "dockerComposeFile": ["test/docker-compose.yml"],
  "service": "lambda",
  "workspaceFolder": "/lambda-python"
}

コンテナ起動後、 Remote Development を使用してPython Lambda実行用のコンテナにアタッチする
Open Folderからソースコード一式を同期した lambda-python フォルダを開く
poetry install 実行後、poetryのinterpreterを選択する

2023-11-06-13-21-43.png

Layer、Lambdaに含める外部パッケージは以下コマンドでpythonフォルダ以下にインストールする

pip install -r requirements.txt -t python/

Pythonデバッグに必要な拡張機能 ms-python.python をインストールする

2023-11-06-13-26-01.png

test/sample-function/test.py を開いてデバッグ実行を行う

2023-11-06-13-23-14.png

2023-11-06-13-24-14.png

AWSサービス(S3)をLocalStackでモック化

Python Lambda - コンテナ上でのローカルデバッグ環境構築(AWSサービス(S3)のモック化)

参考

0
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
0
2