はじめに
- AWS SAM CLI for LocalStack を使ってアプリをLocalStackにデプロイできる
- Dockerでhttpdを起動した端末とスマホが同じネットワークにいれば、スマホのブラウザからWebページを閲覧できる
…ということから、「Dockerで動いているLocalStackにデプロイしたLambda関数へ、同じネットワークのAndroidアプリからアクセスできるのでは?」などと思いつきました。試してみたところ、一応できたのでここに残しておきます
AWSとスマホアプリを連携させるケースを、不具合の混入や費用などの心配なくローカルで好き勝手に試したい、という方の参考になれば幸いです
ちなみに当方はAndroid専門なので、iOSについては言及しておりません。申し訳ありませんが、ご了承ください
追記
私のGitHubに以下の3点を含むレポジトリを共有しております。よければご参考ください
- LocalStackコンテナを起動するための docker-compose.yaml
- 簡単なSAMプロジェクト
- Lambda関数を呼び出せす簡単なAndroidアプリ
実行環境について
このエントリを書くにあたり、以下の環境で作業を行いました
- MacとAndroid端末を用意し、両者を同じネットワークに接続
- MacにDockerをインストールし、コンテナでLocalStackを起動
- AWS SAM CLI for LocalStackを使ってアプリをビルド、デプロイ
- アプリに含まれるLambda関数は、REST APIとして呼び出せるよう設定
- APIにリクエストをかけるAndroidアプリを用意して、Lambdaからのレスポンスが得られるかを確認
ソフトウェアのバージョン
AWS関連
% aws --version
aws-cli/2.17.13 Python/3.11.9 Darwin/23.6.0 exe/x86_64
% sam --version
SAM CLI, version 1.121.0
LocalStack関連
% docker compose up
[+] Running 1/0
✔ Container localstack-main Created 0.0s
Attaching to localstack-main
localstack-main | LocalStack version: 3.5.1.dev
localstack-main | LocalStack build date: 2024-07-19
localstack-main | LocalStack build git hash: 9d37d8285
localstack-main | Ready.
Android関連
- Android Studio Koala | 2024.1.1
- Pixel5 (Android 14)
その他
- macOS sonoma
- Docker Desktop 27.1.1, build 6312585
- Python 3.12.5
SAMを使ったアプリのビルドとデプロイ
前提条件
PythonやDocker Desktop以外に、AWS CLIとSAM CLIがインストール済みとします
手順
基本的には下記を実施すれば、アプリをLocalStackにデプロイできます(場合によっては不要な作業もあります)
- LocalStack AWS CLI のセットアップ
- AWS SAM CLI for LocalStack のセットアップ
- docker-compose.yaml で
SERVICES
環境変数をセット -
AWS_ENDPOINT_URL
環境変数をセット(必要に応じて) -
samlocal
コマンドを使って、アプリをビルド・デプロイ
LocalStack AWS CLI のセットアップ
% pip install awscli-local
% awslocal --version
aws-cli/2.17.13 Python/3.11.9 Darwin/23.6.0 exe/x86_64
AWS SAM CLI for LocalStack のセットアップ
% pip install aws-sam-cli-local
% samlocal --version
SAM CLI, version 1.122.0
docker-compose.yaml で SERVICES 環境変数をセット
- LocalStackでエミュレーションするAWSサービスの一覧を
SERVICES
という環境変数に列挙します - SAMでのデプロイにCloudFormationが必要だったり、ロール付与のためにIAMが必要なので、以下を指定しておくのが無難だと思います
logs
cloudformation
-
iam
- テンプレートに定義されているサービスが
SERVICES
に無いとsamlocal deploy
でエラーになります- 例えばREST APIとしてLambdaを起動する場合は
apigateway
が必要です
- 例えばREST APIとしてLambdaを起動する場合は
- 私が実際に使用した docker-compose.yaml は こちら でご確認ください
(例) 必要な SERVICES を指定しないとどうなるか
cloudformation
を SERVICES
に指定しないで samlocal deploy
を実行した場合です。下記のエラーが発生してデプロイに失敗します
% samlocal deploy --config-env local
Creating the required resources...
Error: Failed to create managed resources: An error occurred (InternalFailure) when calling the CreateChangeSet operation: Service 'cloudformation' is not enabled. Please check your 'SERVICES' configuration variable.
AWS_ENDPOINT_URL 環境変数をセット(必要に応じて)
- こちらは docker-compose.yaml でなく、
awslocal
コマンドやsamlocal
コマンドを発行する側にセットします。このエントリの場合、Macのターミナルでexport
することになります -
AWS_ENDPOINT_URL
環境変数によって、DockerコンテナにセットアップしたLocalStackがsamlocal
コマンドの相手として設定されます-
aws
コマンド発行時にendpoint-url
を指定するのと同様の効果があります -
AWS_ENDPOINT_URL
のデフォルトは http://localhost.localstack.cloud:4566 です。そのためコンテナの設定でポート番号などを変更していなければ、AWS_ENDPOINT_URL
を設定しなくてもsamlocal
は期待通りに機能します。状況に応じて設定して下さい
-
アプリのビルド・デプロイ
- 実環境に対して
sam
コマンドを発行するのと同様、samlocal
コマンドを使ってLocalStackにアプリをビルド・デプロイします- 下記の例では何もオプションを指定していませんが、必要に応じて
--guided
などを指定してください
- 下記の例では何もオプションを指定していませんが、必要に応じて
- ビルドには
samlocal
でなくsam
コマンドでも構いませんが、deploy
には必ずsamlocal
を使うようにしてください
samlocal build
samlocal deploy
Lambda関数をAPIとして起動
同じネットワークに繋がっており、エンドポイントが分かれば、基本的にはcURLでもAndroidアプリでも、同じようにLambda関数に対するリクエストをかけることができます
Lambdaの設定
AWS::Serverless::Function
の Events
は以下のように設定されているとします
(必要な箇所だけ抜粋)
Type: AWS::Serverless::Function
Properties:
Events:
SimpleResponseApiEvent:
Type: Api
Properties:
Method: get
Path: /sample
エンドポイントの確認
-
awslocal apigateway get-rest-apis コマンドでREST API IDを取得
- 実行結果の “items” > “id” から取得できます(実行例を後掲してあります)
- LocalStack のリファレンスを参考に、Lambda関数を起動するためのURLを割り出します
REST API IDからエンドポイントを割り出す
エンドポイントのルールは以下の通りです
ここではホスト名が localhost になっていますが、他の端末からアクセスする場合は、LocalStackの稼働している端末のIPアドレスに置き換えてください
http://localhost:4566/restapis/[REST API ID]/[パス]/_user_request_/[パス]?[クエリ]
apigateway get-rest-apis
で確認したREST API IDが “abcde12345” だった場合、Lambda関数にアクセスするためのエンドポイントは以下のようになります
# クエリを必要としない場合
http://localhost:4566/restapis/abcde12345/sample/_user_request_/sample
# param というキーでクエリを利用する場合
http://localhost:4566/restapis/abcde12345/sample/_user_request_/sample?param=XXXXXX
ここまでで、cURLなりAndroid端末なりで目的の関数にリクエストをかけることができます
curl http://localhost:4566/restapis/abcde12345/sample/_user_request_/sample
(参考) awslocal apigateway get-rest-apis の実行結果
% awslocal apigateway get-rest-apis
{
"items": [
{
"id": "8g99upccg5",
"name": "sample-sam-app-local-ServerlessRestApi-9a7a3dda",
"createdDate": "2024-08-28T13:57:18+09:00",
"version": "1.0",
"apiKeySource": "HEADER",
"endpointConfiguration": { "types": [ "EDGE" ] },
"tags": {
"aws:cloudformation:logical-id": "ServerlessRestApi",
"aws:cloudformation:stack-name": "sample-sam-app-local",
"aws:cloudformation:stack-id": "arn:aws:cloudformation:ap-northeast-3:000000000000:stack/sample-sam-app-local/ac48696f"
},
"disableExecuteApiEndpoint": false,
"rootResourceId": "8pv2rh0na7"
}
]
}