はじめに
業務の一環でAmplifyにホストしたTypeScript ReactベースのwebアプリからPython実装のAPIを使いたかった。初手として、Amplify CLIを用いてLambda+API Gatewayを使った実装を試行したので、備忘をここに残す。
この記事のゴールはAmplify CLIでapiを追加してpushするところまで。
環境
- OS macOS Sonoma 14.4.1
- AWS Amplify CLI 12.11.1
- Node.js v20.11.0
- npm 10.2.4
- TypeScript 5.3.3
- React 18.2.0
- Python 3.12.1
前提
AmplifyにAuthとStorageを追加済み。ここからPython実装のAPIを追加する。
inakason@buz web-app % amplify status
Current Environment: dev
┌──────────┬─────────────────┬───────────┬───────────────────┐
│ Category │ Resource name │ Operation │ Provider plugin │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Auth │ webapp │ No Change │ awscloudformation │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Storage │ ffdwebappstrage │ No Change │ awscloudformation │
└──────────┴─────────────────┴───────────┴───────────────────┘
APIの追加
まず、amplify add api
から要件に併せてapiの設定を行っていく。
inakason@buz web-app % amplify add api
? Select from one of the below mentioned services: REST
✔ Provide a friendly name for your resource to be used as a label for this category in the project: · ffdexecutorapi
✔ Provide a path (e.g., /book/{isbn}): · /coffee
Only one option for [Choose a Lambda source]. Selecting [Create a new Lambda function].
? Provide an AWS Lambda function name: ffdexecutorapi
? Choose the runtime that you want to use: Python
⚠️ You must have pipenv installed and available on your PATH as "pipenv". It can be installed by running "pip3 install --user pipenv".
You must have virtualenv installed and available on your PATH as "venv". It can be installed by running "pip3 install venv".
Only one template found - using Hello World by default.
✅ Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation
- Lambda layers configuration
- Environment variables configuration
- Secret values configuration
? Do you want to configure advanced settings? Yes
? Do you want to access other resources in this project from your Lambda function? Yes
? Select the categories you want this function to have access to. auth, storage
? Select the operations you want to permit on webapp80c33697 read
? Select the operations you want to permit on ffdwebappstrage create, read, update, delete
You can access the following resource attributes as environment variables from your Lambda function
AUTH_WEBAPP80C33697_USERPOOLID
ENV
REGION
STORAGE_FFDWEBAPPSTRAGE_BUCKETNAME
? Do you want to invoke this function on a recurring schedule? No
? Do you want to enable Lambda layers for this function? No
? Do you want to configure environment variables for this function? No
? Do you want to configure secret values this function can access? No
? Do you want to edit the local lambda function now? Yes
Edit the file in your editor: /Users/***mask***/amplify/backend/function/ffdexecutorapi/src/index.py
? Press enter to continue
✅ Successfully added resource ffdexecutorapi locally.
✅ Next steps:
Check out sample function code generated in <project-dir>/amplify/backend/function/ffdexecutorapi/src
"amplify function build" builds all of your functions currently in the project
"amplify mock function <functionName>" runs your function locally
To access AWS resources outside of this Amplify app, edit the /Users/***mask***/amplify/backend/function/ffdexecutorapi/custom-policies.json
"amplify push" builds all of your local backend resources and provisions them in the cloud
"amplify publish" builds all of your local backend and front-end resources (if you added hosting category) and provisions them in the cloud
✅ Succesfully added the Lambda function locally
✔ Restrict API access? (Y/n) · yes
✔ Who should have access? · Authenticated and Guest users
✔ What permissions do you want to grant to Authenticated users? · create, read, update, delete
✔ What permissions do you want to grant to Guest users? · create, read, update, delete
✔ Do you want to add another path? (y/N) · no
✅ Successfully added resource ffdexecutorapi locally
✅ Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud
設定の更新
ここで、Lambda Layerの追加はNoとしているが、実行時にはLayerを作成してなかったため、Layer作成後に再度amplify update function
でLambda LayerのARNを指定した。
inakason@buz web-app % amplify update function
? Select the Lambda function you want to update ffdexecutorapi
General information
- Name: ffdexecutorapi
- Runtime: python
Resource access permission
- webapp (read)
- ffdwebappstrage (create, read, update, delete)
Scheduled recurring invocation
- Not configured
Lambda layers
- Not configured
Environment variables:
- Not configured
Secrets configuration
- Not configured
? Which setting do you want to update? Lambda layers configuration
? Do you want to enable Lambda layers for this function? Yes
? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:ap-northeast-1:***mask***:layer:trimesh:1,arn:aws:lambda:
ap-northeast-1:***mask***:layer:PyGeM:1
✔ Modify the layer order (Layers with conflicting files will overwrite contents of layers earlier in the list): · arn:aws:lambda:ap-northeast-1:***mask***:layer:trimesh:1, arn:aws:lambda:ap-northeast-1:***mask***:layer:PyGeM:1
? Do you want to edit the local lambda function now? Yes
Edit the file in your editor: /Users/***mask***/amplify/backend/function/ffdexecutorapi/src/index.py
? Press enter to continue
pipenvとvenvのインストール
先ほどamplify add api
とした時に以下の警告が出現していた。
You must have pipenv installed and available on your PATH as "pipenv". It can be installed by running "pip3 install --user pipenv".
You must have virtualenv installed and available on your PATH as "venv". It can be installed by running "pip3 install venv".shell
実はこれはpip3ではなく、brewでインストールすることで解決できた。したがって、以下のコマンドを実行。
inakason@buz web-app % brew install pipenv
inakason@buz web-app % brew install virtualenv
ランタイム設定の変更
このまま、amplify push
としてもPythonのバージョン違いでエラーが出てしまう。
inakason@buz web-app % amplify push
✔ Successfully pulled backend environment dev from the cloud.
Current Environment: dev
┌──────────┬─────────────────┬───────────┬───────────────────┐
│ Category │ Resource name │ Operation │ Provider plugin │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Function │ ffdexecutorapi │ Create │ awscloudformation │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Api │ ffdexecutorapi │ Create │ awscloudformation │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Auth │ webapp │ No Change │ awscloudformation │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Storage │ ffdwebappstrage │ No Change │ awscloudformation │
└──────────┴─────────────────┴───────────┴───────────────────┘
✔ Are you sure you want to continue? (Y/n) · yes
Courtesy Notice: Pipenv found itself running within a virtual environment, so it will automatically use that environment, instead of creating its own for any project. You can set PIPENV_IGNORE_VIRTUALENVS=1 to force pipenv to ignore that environment and create its own instead. You can set PIPENV_VERBOSITY=-1 to suppress this warning.
Pipfile.lock not found, creating...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✔ Success!
Locking [dev-packages] dependencies...
Updated Pipfile.lock (20a5580e79d8b5a7a360dfdbab4ee3c05dce7388bd6c4f2e7c30c18288e02f68)!
Installing dependencies from Pipfile.lock (e02f68)...
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
🛑 Could not find a pipenv site-packages directory at /Users/***mask***/.pyenv/versions/3.12.1/envs/myenv/lib/python3.8/site-packages
Learn more at: https://docs.amplify.aws/cli/project/troubleshooting/
どうやら、Python3.12で実装しようとしているのに対して、CI/CDでインストールされるPythonのバージョンが3.8('24年5月時点)であることが問題のようだ。
そこで、以下の変更を加える必要がある。参考はこちら。
amplify.ymlのバックエンドビルドコマンドの変更
AWSマネジメントコンソールから開発中のアプリを選択、左のツールバーからホスティング→ビルドの設定からamplify.yml
でビルドの設定ができる。update-alternatives
コマンドをバックエンドのビルドコマンドに追加する。フロントエンドの箇所は元からあったものなので、変更は加えていない。
version: 1
backend:
phases:
build:
commands:
- echo "Installing Python 3.12..."
- pyenv install 3.12.0
- pyenv global 3.12.0
- python --version
- echo "Python 3.12 installed and configured."
frontend:
phases:
preBuild:
commands:
- npm ci --cache .npm --prefer-offline
build:
commands:
- npm run build
artifacts:
baseDirectory: build
files:
- '**/*'
cache:
paths:
- .npm/**/*
Pipfileのrequire pythonバージョンを変更
amplify/backend/function/ffdexecutorapi/Pipfile
内にあるpython_versionを3.8から3.12に変更する。(ffdexecutorapiは作成したLambda関数名)
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
src = {editable = true, path = "./src"}
[requires]
python_version = "3.12"
cloudformation-templateのランタイムを変更
amplify/backend/function/ffdexecutorapi/ffdexecutorapi-cloudformation-template.json
内にあるPythonランタイムを3.8から3.12に変更
(略)
"Runtime": "python3.12",
"Layers": [
"arn:aws:lambda:ap-northeast-1:***mask***:layer:trimesh:1",
"arn:aws:lambda:ap-northeast-1:***mask***:layer:PyGeM:1"
],
"Timeout": 25
(略)
このファイルでLambdaの諸々設定を触ることができる。今回、開発環境はMacなので、Lambdaアーキテクチャはarm64にしたいところ。この場合上記にさらにArchitectures
の値を設定する。(Resources->Properties下にネスト)
(略)
"Architectures": ["arm64"]
(略)
Amplify push
amplify push
を実行する前に、環境変数PIPENV_IGNORE_VIRTUALENVS=1
を設定する。こうすることで、Pipenvが現在の仮想環境を無視して、新しい環境を作成してくれる。これを設定せずにamplify push
すると、ローカルにインストールしたライブラリ全てを含めてLambdaへデプロイしてしまうので、許容上限(≒250MB)を超えてエラーとなってしまう。
inakason@buz web-app % export PIPENV_IGNORE_VIRTUALENVS=1
これで、ようやくamplify push
できるようになる。
inakason@buz web-app % amplify push
✔ Successfully pulled backend environment dev from the cloud.
Current Environment: dev
┌──────────┬─────────────────┬───────────┬───────────────────┐
│ Category │ Resource name │ Operation │ Provider plugin │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Function │ ffdexecutorapi │ Create │ awscloudformation │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Api │ ffdexecutorapi │ Create │ awscloudformation │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Auth │ webapp │ No Change │ awscloudformation │
├──────────┼─────────────────┼───────────┼───────────────────┤
│ Storage │ ffdwebappstrage │ No Change │ awscloudformation │
└──────────┴─────────────────┴───────────┴───────────────────┘
✔ Are you sure you want to continue? (Y/n) · yes
Creating a virtualenv for this project...
Pipfile: /Users/***mask***/amplify/backend/function/ffdexecutorapi/Pipfile
Using /opt/homebrew/Cellar/python@3.12/3.12.3/Frameworks/Python.framework/Versions/3.12/bin/python3 (3.12.3) to create virtualenv...
⠹ Creating virtual environment...created virtual environment CPython3.12.3.final.0-64 in 886ms
creator CPython3macOsBrew(dest=/Users/inakason/.local/share/virtualenvs/ffdexecutorapi-GykZc1Qo, clear=False, no_vcs_ignore=False, global=False)
seeder FromAppData(download=False, pip=bundle, via=copy, app_data_dir=/Users/inakason/Library/Application Support/virtualenv)
added seed packages: pip==23.3.1
activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
✔ Successfully created virtual environment!
Virtualenv location: /Users/inakason/.local/share/virtualenvs/ffdexecutorapi-GykZc1Qo
Installing dependencies from Pipfile.lock (4a2311)...
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Deployment completed.
Deployed root stack webapp [ ======================================== ] 5/5
amplify-webapp-dev-fa745 AWS::CloudFormation::Stack UPDATE_COMPLETE Mon May 13 2024
storageffdwebappstrage AWS::CloudFormation::Stack UPDATE_COMPLETE Mon May 13 2024
authwebapp80c33697 AWS::CloudFormation::Stack UPDATE_COMPLETE Mon May 13 2024
functionffdexecutorapi AWS::CloudFormation::Stack CREATE_COMPLETE Mon May 13 2024
apiffdexecutorapi AWS::CloudFormation::Stack CREATE_COMPLETE Mon May 13 2024
Deployed function ffdexecutorapi [ ======================================== ] 4/4
LambdaExecutionRole AWS::IAM::Role CREATE_COMPLETE Mon May 13 2024
AmplifyResourcesPolicy AWS::IAM::Policy CREATE_IN_PROGRESS Mon May 13 2024
LambdaFunction AWS::Lambda::Function CREATE_IN_PROGRESS Mon May 13 2024
Deployed api ffdexecutorapi [ ======================================== ] 5/5
Deployment state saved successfully.
REST API endpoint: https://***mask***.execute-api.ap-northeast-1.amazonaws.com/dev
Browserslist: caniuse-lite is outdated. Please run:
npx update-browserslist-db@latest
Why you should do it regularly: https://github.com/browserslist/update-db#readme
No AppSync API configured. Please add an API
おわりに
結局、Lambdaデプロイのサイズ上限250MBをクリアできず、amplify remove api
とamplify remove function
して別途手動でimageタイプのLambdaを組みました。
この案件がうまくいくことを心より願っています。