前書き
個人開発や技術検証で、試行錯誤しながらとにかく手を動かしたいとき、デプロイをもっと簡単にしたいと考えています。
Lambdaのランタイムをイメージにする方法もありますが、スクリプトを作成せず、コマンド一発でイメージをビルドし直し、ECRにプッシュするなど、スムーズに処理できる方法がなかなか見つかりません。もし、良い方法があれば教えていただきたいです。
現状はFunctionとLayerを分ける形で対応していますが、これはあくまで妥協案です。とはいえ、一応使える状態にはなっています。
手順
AWS CDK プロジェクトのセットアップ
mkdir my-lambda-project
cd my-lambda-project
cdk init app --language=typescript
aws-lambda
と aws-lambda-python-alpha
ライブラリをインストールします。
npm install aws-cdk-lib @aws-cdk/aws-lambda-python-alpha
ディレクトリとファイルの抜粋は下記の通り
my-lambda-project/
├── bin/
├── lib/
| ├── my-lambda-project-stack.ts # CDN stackの Typescript コード
│ ├── lambda/
│ │ ├── index.py # Lambda 関数の Python コード
│ ├── lambda-layer/
│ │ ├── requirements.txt # Lambda レイヤの Python コード
├── node_modules/
├── cdk.json
├── package.json
└── tsconfig.json
CDKのstackの定義
my-lambda-project-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as lambda_python from '@aws-cdk/aws-lambda-python-alpha';
import * as path from 'path';
export class MyLambdaProjectStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const layer = new lambda_python.PythonLayerVersion(this, "MyLayer", {
entry: path.join(__dirname, 'lambda-layer'),
compatibleRuntimes: [lambda.Runtime.PYTHON_3_9],
});
const myFunction = new lambda_python.PythonFunction(this, 'MyFunction', {
entry: path.join(__dirname, 'lambda'),
runtime: lambda.Runtime.PYTHON_3_9,
layers: [layer],
});
}
}
lambda-layer/requirements.txt
requirements.txt
requests==2.27.1
beautifulsoup4==4.12.3
index.py
import json
import requests
from bs4 import BeautifulSoup
def handler(event, context):
url = "https://aws.amazon.com/jp/blogs/aws/"
response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
articles = soup.select("article.blog-post")[:1]
result = []
for article in articles:
title = article.select_one("h2.blog-post-title").text.strip()
link = article.select_one("h2.blog-post-title a")["href"]
date = article.select_one("footer.blog-post-meta").text.strip()
result .append({"title": title, "link": link, "date": date})
contents = json.dumps(result, ensure_ascii=False)
response_body = {"application/json": {"body": contents}}
action_response = {
"actionGroup": event.get("actionGroup", "default_action_group"),
"apiPath": event.get("apiPath", "/default_path"),
"httpMethod": event.get("httpMethod", "GET"),
"httpStatusCode": 200,
"responseBody": response_body,
}
api_response = {"messageVersion": "1.0", "response": action_response}
return api_response
デプロイ
npx cdk deploy