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」を押して
3-2. コンテナ内に接続
DEv Containersの階層の下にある
「 →のボタン Attach In Current Window , + のボタン Attach In New Window」を押す
なお、Other Containersの階層の下には表示されない
3-3. VS Codeeでコンテナを開いた後のイメージ
左下で 「>< 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
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ファイル)を保持します
- 変更例
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 ライブラリを使う場合
サンプル
- https://github.com/ssugimoto/serverless-framework-python-example2/tree/develop/app/lambda-lib-sample
参考ドキュメント
作成方法
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ファイルも作成されます
plugins:
- serverless-python-requirements
7-3. requirements.txt を作成
必要なライブラリとバージョンを指定する
boto3>=1.28.43
7-4. パッケージングのための調整
package:
individually: false
patterns:
- '!**/*'
- handler.py
7-5. サンプルソースでは Lambda function一覧を取得するので、LambdaのIAMロールに権限を付与
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を動かすことで個人の環境に依存しない、ローカル環境を汚さない、バージョン違いでの無用なトラブル防止に役立つ