ブログ

AWS SAM 入門|サーバーレス開発を効率化する AWS SAM の基本と実践

エンジニアの横田です。

最近 SAM を触る機会が多く、その使い勝手の良さを社内エンジニアにこっそり広めようとしています。

そういえば弊社ブログで取り扱ったことがなかったなと思い、おさらいも兼ねて本ブログを執筆いたしました。

本ブログでは初めての方でも安心して使えるよう、SAM の基本概念からサンプル構築、ローカルテスト方法、そして運用のベストプラクティスを紹介します。
本ブログの内容が読者の皆様の SAM 理解の一助となれば幸いです。

※ 本ブログの情報は 2025/06/10 時点の情報です。

AWS SAM 入門|サーバレスアプリ構築の基礎

AWS SAM (Serverless Application Model) とは、AWS が提供する、Lambda 関数や Amazon API Gateway、Amazon DynamoDB、Amazon S3 といったサーバレスリソースを一括管理するためのフレームワークです。

AWS CloudFormation を拡張し、Lambda 関数や API Gateway、DynamoDB テーブルなどサーバーレスリソースを簡潔に宣言できる独自の構文を提供します。

SAM テンプレート(YAML形式)1つでアプリケーション全体を定義し、sam build や sam deploy コマンドでビルドとデプロイを自動化できます。

これにより、複雑な CloudFormation テンプレートを手書きする手間が省け、サーバーレス開発の生産性が飛躍的に向上します。

SAM の主要コンポーネントは以下の通りです。

  • テンプレートファイル:template.yaml で構成。リソース定義、パラメータ、出力などを記述。
  • リソースタイプ:AWS::Serverless::Function、AWS::Serverless::Api、AWS::Serverless::SimpleTable など。
  • CLI ツール:sam init でプロジェクト雛形作成、sam build で依存関係をパッケージ化、sam deploy で AWS にデプロイ。

また、SAM CLI の sam local コマンドを使用すると、ローカルで簡単にテストやデバッグが行え、開発効率が大幅に向上します。

AWS SAM 入門|Hello World Lambda + API Gateway を構築

まずは最小構成のサーバーレスアプリを作成し、動作を確認しましょう。
今回紹介する手順は、SAM CLI の対話形式ガイドに沿って進めるため、初めてでも迷わず進められると思います。

  1. プロジェクト作成
    • PythonやNode.jsなど、希望のランタイムを選択
    • プロジェクト名やデフォルトAPIパスを指定
  1. テンプレート編集
    • 関数リソースやAPIエンドポイント定義を追加
    • 必要に応じて環境変数やLayerを設定
  1. ビルド
    • ローカル環境に依存関係をキャッシュし、再現性のあるパッケージを生成
  1. デプロイ
    • --guidedオプションを利用すると、S3バケットやスタック名、リージョンを対話的に決定可能

それでは実際に進めていきます。

1. プロジェクト作成

sam init を実行すると対話形式でプロジェクトが作成されます。
今回は 「 1 - AWS Quick Start Templates 」 > 「 1 - Hello World Example 」 を選択後、その他項目についてはすべてデフォルト値で作成します。

# sam init --runtime python3.12 --name hello-sam
# cd hello-sam


2. テンプレート編集 (template.yaml)

今回はデフォルトで作成されたテンプレートをそのまま使用します。

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

  Sample SAM Template for hello-sam

# 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.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64
      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

3. コード編集 (hello-sam/app.py)

こちらもデフォルト作成されたものをそのまま使用します。

import json

# import requests


def lambda_handler(event, context):
    """Sample pure Lambda function

    Parameters
    ----------
    event: dict, required
        API Gateway Lambda Proxy Input Format

        Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format

    context: object, required
        Lambda Context runtime methods and attributes

        Context doc: https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    Returns
    ------
    API Gateway Lambda Proxy Output Format: dict

        Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
    """

    # try:
    #     ip = requests.get("http://checkip.amazonaws.com/")
    # except requests.RequestException as e:
    #     # Send some context about this error to Lambda Logs
    #     print(e)

    #     raise e

    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello world",
            # "location": ip.text.replace("\n", "")
        }),
    }

4. ビルド&デプロイ

デプロイ時に changeset の適用可否の確認が対話形式で表示されます。
問題なければ y を入力しデプロイします。

# sam build
# sam deploy

これで、API Gatewayのエンドポイントにアクセスすると「hello world」が返ってきます。
CLIの対話形式でパラメータを設定でき、初回デプロイも迷わず進められます。

AWS SAM 入門|sam local でのローカルデバッグ&テスト

SAM CLI には、AWS リソースをローカル環境でエミュレートするコマンドが用意されています。
ここでは、sam local の活用方法を紹介します。

1. sam local start-api

概要:

API Gateway の GET/POST/PUT/DELETE などの HTTP イベントをローカルサーバーにマッピングし、Lambda 関数をコンテナ内で実行します。

実行サンプル:

下記コマンドで、localhost に API Gateway が立ち上がり、http://127.0.0.1:3000/hello にアクセスすると Lambda が起動します。ログ出力には、Lambda 実行時間やレスポンスサイズ、エラー情報が詳細に表示されるため、パフォーマンスチューニングの第一歩として活用できます。

2. sam local invoke

概要:

Lambda 関数単体の実行テストができ、イベントペイロードを自由に変更してテストケースを増やせます。

実行サンプル:

下記手順で実行します。

① イベントペイロードファイルを作成。

プロジェクト作成手順の完了時点で /events/event.json が作成されているため、そのまま使用します。

{
  "body": "{\"message\": \"hello world\"}",
  "resource": "/hello",
  "path": "/hello",
  "httpMethod": "GET",
  "isBase64Encoded": false,
  "queryStringParameters": {
    "foo": "bar"
  },
  "pathParameters": {
    "proxy": "/path/to/resource"
  },
  "stageVariables": {
    "baz": "qux"
  },
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, sdch",
    "Accept-Language": "en-US,en;q=0.8",
    "Cache-Control": "max-age=0",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Desktop-Viewer": "true",
    "CloudFront-Is-Mobile-Viewer": "false",
    "CloudFront-Is-SmartTV-Viewer": "false",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Viewer-Country": "US",
    "Host": "1234567890.execute-api.us-east-1.amazonaws.com",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Custom User Agent String",
    "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
    "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
    "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "requestContext": {
    "accountId": "123456789012",
    "resourceId": "123456",
    "stage": "prod",
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "requestTime": "09/Apr/2015:12:34:56 +0000",
    "requestTimeEpoch": 1428582896000,
    "identity": {
      "cognitoIdentityPoolId": null,
      "accountId": null,
      "cognitoIdentityId": null,
      "caller": null,
      "accessKey": null,
      "sourceIp": "127.0.0.1",
      "cognitoAuthenticationType": null,
      "cognitoAuthenticationProvider": null,
      "userArn": null,
      "userAgent": "Custom User Agent String",
      "user": null
    },
    "path": "/prod/hello",
    "resourcePath": "/hello",
    "httpMethod": "POST",
    "apiId": "1234567890",
    "protocol": "HTTP/1.1"
  }
}

② sam local invoke コマンドを実行。

template.yaml で定義した Function 名を指定して実行します。

# sam local invoke HelloWorldFunction --event events/event.json
Invoking app.lambda_handler (python3.12)                                                                                                                                                                                          
Local image is up-to-date                                                                                                                                                                                                         
Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64.                                                                                                                                                                
                                                                                                                                                                                                                                  
Mounting /Users/xxxx/work/hello-sam/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated, inside runtime container    

START RequestId: dd0116dc-cf76-4fc4-82e7-0338c70d236d Version: $LATEST
END RequestId: f158d88c-3bf1-4578-9fbb-64da4ba86333
REPORT RequestId: f158d88c-3bf1-4578-9fbb-64da4ba86333  Init Duration: 0.77 ms  Duration: 520.65 ms     Billed Duration: 521 ms Memory Size: 128 MB     Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}

このように sam local invoke を使うことで、AWS へのデプロイを行わずとも関数単体の動作確認が簡単に行えます。

テスト用の JSON ファイルを増やすことで、複数ケースの自動テストにも活用できます。

AWS SAM 入門|デプロイ&運用ポイント

SAM を本番運用する際のベストプラクティスを紹介します。

  • CI/CD パイプライン連携:GitHub Actions や AWS CodePipeline と組み合わせ、sam build → sam deploy を自動化。プルリクエスト合格時に本番環境へ安全にデプロイ。
  • バージョニング&エイリアス:Lambda のバージョン管理とエイリアス設定で、ブルー/グリーンデプロイやカナリアリリースを実現。
  • モニタリング:CloudWatch Logs、X-Ray を有効化し、Lambda 実行状況や API のレイテンシを可視化。アラームを設定して障害検知。
  • セキュリティ:Least Privilege 原則を適用し、SAM テンプレートの Policies セクションで必要最小限の IAM ロールを定義。
  • コスト最適化:関数のメモリ/タイムアウト設定をチューニングし、実行時間とメモリ使用量をバランス調整。

これらを実践することで、AWS SAM を用いたサーバーレスアプリケーションの品質と信頼性を高められます。

AWS SAM 入門(まとめ)

AWS SAM を活用することでサーバレスアプリケーションの管理とデプロイを効率化できます。

サーバレス開発の出発点としてぜひ AWS SAM を導入し、開発効率と運用品質を向上させてください。

また、「AWS でこんなことできないかな?」「自社サーバーを AWS に引っ越したいな。」等々ございましたら、右上の お問い合わせ からお気軽にご相談ください。

ご参考:ユーザーガイド(AWS)

AWS Serverless Application Model (AWS SAM) とは
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/what-is-sam.html

【筆者実行環境】
PC:MacBook Air (M1, 2020)
OS:macOS Sequoia 15.5
aws cli:aws-cli/2.27.31 Python/3.13.4 Darwin/24.5.0 source/arm64
SAM CLI:version 1.140.0
Docker:version 24.0.2

元記事発行日: 2025年06月25日、最終更新日: 2025年09月02日