【AWS】SAM-CLIでサーバーレスアプリケーション① - プロジェクトの作成とローカルでテスト実行 -

AWSでサーバーレスアプリケーション(SAMアプリケーション)を開発する際の手順をまとめます。

はじめに

サーバーレスアプリケーションとは

バックグラウンドで処理をするアプリケーション(いわゆるLambda関数)

SAM-CLIとは

AWSの提供するクライアント用SAMコマンド(Serverless Application Model - Client)

ローカルでサーバーレスアプリケーションの作成やAWSへのデプロイができる

また、Dockerと組み合わせればローカルでのテスト実行が可能

公式の詳細は以下

https://aws.amazon.com/jp/serverless/sam/

この記事ではSAM-CLIを使ってLambda関数をローカルで実行する手順を紹介します。

実装

プロジェクト作成

sam init

$ sam init

以下のような構成でファイルが作られる。

sam-app/
├── README.MD
├── event.json
├── hello-world
│ └── app.js
│ └── package.json
│ └── tests
│ └── unit
│ └── test-handler.js
├── template.yaml

※もちろんオプションによりプロジェクトの細かい設定が可能です。

※デフォルトで言語はnode.jsが選択されます。(この記事でもnode.jsを使用)

言語の選択

--runtime

--runtime [識別子] で言語を選択可能、以下の識別子が利用できます。

  • 名前(言語) → 識別子
  • Node.js 10(Node.js) → nodejs10.x
  • Node.js 8.10(Node.js) → nodejs8.10
  • Python 3.6(Python) → python3.6
  • Python 3.7(Python) → python3.7
  • Python 2.7(Python) → python2.7
  • Ruby 2.5(Ruby) → ruby2.5
  • Java 8(Java) → java8
  • Go 1.x(Go) → go1.x
  • .NET Core 2.1(C#) → dotnetcore2.1
  • .NET Core 1.0(C#) → dotnetcore1.0

実装コード

app.js

sam initで生成されるapp.jsの内容が以下です。

S3やSQSなどをトリガーにして、バックグラウンドで以下の処理が走るイメージです。

引数のeventでS3なら生成されたオブジェクト、SQSならキューに積まれた内容が取得できます。

exports.lambdaHandler = async (event, context) => {
    try {
        response = { 
            'statusCode': 200,
            'body': JSON.stringify({
                message: 'hello world',
            })  
        }   
    } catch (err) {
        console.log(err);
        return err;
    }

    return response
};

デプロイ設定

template.yaml

Lambda関数の設定などをこのファイルに記述します。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs10.x
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

ResoucesのEventsにLambda関数のトリガーを設定できるはずが、うまくいきませんでした。

やりたいことは「S3の既存バケットにオブジェクトが生成された時」をトリガーにしたかったが、既存のバケットを指定するとデプロイの時にこけてしまいます。

デプロイ後にAWS上からトリガーを手動で設定することで対応しました。

ここではローカルでテストするために、APIによりLambda関数を実行する設定のみを入れておく。(→Events.HelloWorld)

このAPIの設定はデフォルトで入っているが、本来セキュリティの観点から、特に理由がない限り閉じておくとよいです。

Outputsは、デプロイの時にコンソールに表示されるログ。特に必要ないので消してしまってもOK

動作確認

ローカルで実行してみる

$ cd sam-app
$ sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

template.yamlのディレクトリで sam local start-api コマンドを実行するとサーバーが立ち上がります。

Dockerでnginxが起動して入れば、そのままLambda関数を実行できます。

実行するためのAPIも教えてくれるのでそのまま叩いてみます。

$ curl -i http://127.0.0.1:3000/hello
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 25

{"message":"hello world"}

Lambda関数が実行されます。

この時、SAM-CLI側のコンソールでは以下のようなログ(CloudWatchに出力されるやつ)が出力されています。

Invoking app.lambdaHandler (nodejs10.x)

Fetching lambci/lambda:nodejs10.x Docker container image......
Mounting sam-app/hello-world as /var/task:ro,delegated inside runtime container
(CloudWatch↓)
START RequestId: [xxxxx-xxxxx] Version: $LATEST
END RequestId: [xxxxx-xxxxx]
REPORT RequestId: [xxxxx-xxxxx] Duration: 9.94 ms   Billed Duration: 100 ms Memory Size:
(CloudWatch↑)
 128 MB Max Memory Used: 42 MB  
No Content-Type given. Defaulting to 'application/json'.
127.0.0.1 - - [YYYY-MM-DD HH:MM:SS] "GET /hello HTTP/1.1" 200 -

勝手にDockerコンテナにマウントしてくれるので楽です。

備考

以下のQiita記事を参考にしました。

https://qiita.com/te20/items/5a28cef4966c75886218

コメント

  1. The History of the Casino - One of the Most Popular Casinos
    A poormansguidetocasinogambling.com relative newcomer to the world of online gambling, Wynn Las Vegas opened its casinosites.one doors to a new audience of over 600,000 https://sol.edu.kg/ in 2017. kadangpintar This was herzamanindir.com/ the first casino

    返信削除

コメントを投稿

このブログの人気の投稿

docker-compose up で proxyconnect tcp: dial tcp: lookup proxy.example.com: no such host

docker-compose で起動したweb、MySQLに接続できない事象

【PHP】PHP_CodeSnifferを使う(コーディングルールのカスタマイズ)