AWS SAM CLI とは?初心者でもわかる基礎知識
AWS Serverless Application Model Command Line Interface(AWS SAM CLI)は、サーバーレスアプリケーションの開発、テスト、デプロイを効率化するためのツールです。このツールを使用することで、開発者はローカル環境でAWSのサーバーレスリソースを簡単に構築、テスト、デバッグすることができます。
AWS SAM CLI が解決する 3 つの開発課題
- ローカル開発環境の課題
- 問題点: 従来のサーバーレス開発では、コードの動作確認のたびにAWS環境へのデプロイが必要でした。
- 解決策: SAM CLIの
sam localコマンドにより、ローカル環境でLambda関数やAPIのテストが可能に。
# Lambda関数をローカルで実行 sam local invoke "MyFunction" -e events/event.json # APIをローカルで起動 sam local start-api
- デプロイメントの複雑さ
- 問題点: 複数のAWSリソースの連携が必要なアプリケーションのデプロイは煩雑でした。
- 解決策:
template.yamlによる宣言的なインフラ定義とsam deployコマンドによる一括デプロイ。
# template.yamlの例
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
Events:
ApiEvent:
Type: Api
Properties:
Path: /hello
Method: get
- テストとデバッグの困難さ
- 問題点: クラウド環境でのデバッグは時間がかかり、ログの確認も遅延がありました。
- 解決策: ローカルでのステップ実行やログのリアルタイム表示が可能に。
# デバッグモードでLambda関数を実行 sam local invoke -d 5858 "MyFunction" # ログのリアルタイム表示 sam logs -n MyFunction --tail
従来のサーバーレス開発との決定的な違い
1. 開発ワークフローの改善
| 開発フェーズ | 従来の方法 | SAM CLIを使用した方法 |
|---|---|---|
| コード作成 | エディタでコード作成のみ | テンプレートからの自動生成とボイラープレート提供 |
| テスト実行 | AWS環境へのデプロイが必要 | ローカル環境で即時実行可能 |
| デバッグ | CloudWatchログの確認待ち | リアルタイムデバッグ可能 |
2. インフラ管理の変革
SAM CLIは、Infrastructure as Code(IaC)の考え方を完全に取り入れ、アプリケーションコードとインフラ定義を一元管理できます:
- 統合されたテンプレート管理
- 一つの
template.yamlファイルでアプリケーション全体を定義 - バージョン管理システムでインフラの変更履歴を追跡可能
- テンプレートの再利用による開発の標準化
- 簡素化されたデプロイメントプロセス
# ビルドからデプロイまでワンコマンド sam build && sam deploy --guided
3. 開発体験の向上
SAM CLIの導入により、以下の点で開発者体験が大きく改善されます:
- 高速なフィードバックループ
- コード変更→テスト→デバッグのサイクルが数分から数秒に短縮
- ホットリロード機能によるリアルタイムな変更反映
- 統合された開発環境
- VS Code、IntelliJ等の主要IDEとの連携
- デバッガーやテストランナーとの seamless な統合
このように、AWS SAM CLIは単なるコマンドラインツールではなく、モダンなサーバーレス開発のための包括的な開発環境を提供します。従来の開発手法と比較して、生産性、品質、開発者体験のすべての面で大きな改善をもたらします。
AWS SAM CLI 環境構築完全ガイド
AWS SAM CLIを効果的に使用するためには、適切な環境構築が不可欠です。このガイドでは、各OSでの詳細なセットアップ手順とトラブルシューティングについて解説します。
MacOS/Windows/Linux それぞれの構築手順
MacOS での環境構築
- 前提条件のインストール
# Homebrewのインストール(未導入の場合) /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" # Python3とpipのインストール brew install python3 # Docker Desktopのインストール brew install --cask docker
- AWS SAM CLIのインストール
# AWS SAM CLIのインストール brew install aws-sam-cli # バージョン確認 sam --version
- AWS認証情報の設定
# AWS CLIのインストール brew install awscli # 認証情報の設定 aws configure
Windows での環境構築
- 前提条件のインストール
- Python3.8以上をインストール(公式サイトから)
- Docker Desktopをインストール(WSL2の設定が必要)
- WSL2のセットアップ
# WSL2の有効化(管理者権限で実行) dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
- AWS SAM CLIのインストール
- AWS SAM CLI Windows Installerをダウンロード
- インストーラーを実行
# バージョン確認 sam --version
Linux (Ubuntu/Debian) での環境構築
- 前提条件のインストール
# 必要なパッケージのインストール sudo apt-get update sudo apt-get install -y python3 python3-pip docker.io # Dockerサービスの開始 sudo systemctl start docker sudo systemctl enable docker
- AWS SAM CLIのインストール
# インストールスクリプトのダウンロードと実行 wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip unzip aws-sam-cli-linux-x86_64.zip -d sam-installation sudo ./sam-installation/install
トラブルシューティング – よくあるエラーと解決方法
1. Docker関連の問題
| エラー | 原因 | 解決方法 |
|---|---|---|
Cannot connect to the Docker daemon | Dockerサービスが起動していない | – Dockerデーモンの起動確認 – sudo systemctl start dockerの実行 |
permission denied | Docker権限の問題 | – sudo usermod -aG docker $USERの実行– システムの再起動 |
2. AWS認証関連の問題
# エラー: The config profile (default) could not be found # 解決策:AWS認証情報の再設定 aws configure # 設定項目 AWS Access Key ID: [アクセスキーを入力] AWS Secret Access Key: [シークレットキーを入力] Default region name: [リージョンを入力(例:ap-northeast-1)] Default output format: [json]
3. Python環境の問題
- エラー:
sam: command not found
# 解決策1: PATHの確認と追加 echo $PATH export PATH=$PATH:~/.local/bin # 解決策2: シンボリックリンクの作成 sudo ln -s $(which sam) /usr/local/bin/sam
4. メモリ不足の問題
Docker Desktop設定の調整が必要な場合:
# .samconfig.tomlでのメモリ設定 version = 0.1[default] [default.local_invoke] docker_host = “unix:///var/run/docker.sock” container_memory = 2048 # メモリ制限を2GBに設定
インストール後の動作確認
- 基本的な動作確認
# バージョン確認 sam --version # ヘルプの表示 sam --help
- サンプルプロジェクトの作成
# Hello Worldプロジェクトの作成 sam init --runtime python3.9 --dependency-manager pip --app-template hello-world # プロジェクトのビルド cd sam-app sam build # ローカルでの実行テスト sam local invoke
- 環境変数の設定確認
# AWS認証情報の確認 aws sts get-caller-identity # SAM設定の確認 sam local generate-event s3 put --help
これらの手順を完了することで、AWS SAM CLIの開発環境が整います。トラブルが発生した場合は、上記のトラブルシューティングガイドを参照しながら、系統的に問題を解決していくことをお勧めします。
AWS SAM CLIによるローカル開発の始め方
ローカル環境でのサーバーレスアプリケーション開発を効率的に進めるためのベストプラクティスと実践的な手法を解説します。
SAMテンプレートの作成とプロジェクト構成のベストプラクティス
1. 効率的なプロジェクト構造
my-serverless-app/ ├── template.yaml # メインのSAMテンプレート ├── src/ │ ├── handlers/ # Lambda関数のハンドラー │ │ ├── create-user/ │ │ │ ├── index.js │ │ │ └── package.json │ │ └── process-order/ │ │ ├── index.js │ │ └── package.json │ ├── layers/ # Lambda レイヤー │ │ └── common-libs/ │ └── utils/ # 共通ユーティリティ ├── tests/ │ ├── unit/ │ └── integration/ ├── events/ # テスト用イベント │ ├── create-user.json │ └── process-order.json └── samconfig.toml # SAM CLI設定
2. テンプレート設計のベストプラクティス
# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: サーバーレスアプリケーションのテンプレート
Globals:
Function:
Timeout: 30
MemorySize: 128
Runtime: nodejs18.x
Environment:
Variables:
STAGE: !Ref Stage
Parameters:
Stage:
Type: String
Default: dev
AllowedValues:
- dev
- stg
- prod
Resources:
CreateUserFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
CodeUri: src/handlers/create-user/
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref UsersTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /users
Method: post
UsersTable:
Type: AWS::Serverless::SimpleTable
Properties:
PrimaryKey:
Name: userId
Type: String
Outputs:
ApiEndpoint:
Description: API Gateway endpoint URL
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/${Stage}/"
Lambda関数のローカルテスト実行方法
1. ユニットテストの実装
// tests/unit/create-user.test.js
const { handler } = require('../../src/handlers/create-user');
describe('CreateUser Lambda', () => {
it('should create a new user successfully', async () => {
const event = {
body: JSON.stringify({
email: 'test@example.com',
name: 'Test User'
})
};
const result = await handler(event);
expect(result.statusCode).toBe(200);
});
});
2. ローカルでのLambda実行
# イベントファイルを使用した実行 sam local invoke CreateUserFunction -e events/create-user.json # 環境変数の上書き sam local invoke CreateUserFunction \ -e events/create-user.json \ --env-vars env.json # ホットリロードでの実行(開発効率向上) sam local invoke CreateUserFunction \ -e events/create-user.json \ --hot-reload
APIのテストローカルとデバッグ手法
1. ローカルAPIサーバーの起動
# APIのローカル起動 sam local start-api # デバッグモードでの起動 sam local start-api -d 5858 # 特定のポートでの起動 sam local start-api -p 3000
2. 高度なデバッグテクニック
- VSCodeでのデバッグ設定
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "SAM CLI CreateUser",
"type": "node",
"request": "attach",
"address": "localhost",
"port": 5858,
"localRoot": "${workspaceFolder}/src/handlers/create-user",
"remoteRoot": "/var/task",
"protocol": "inspector",
"stopOnEntry": false
}
]
}
- 効果的なログ出力
// src/handlers/create-user/index.js
const handler = async (event) => {
console.log('Event:', JSON.stringify(event, null, 2));
try {
// 処理内容
console.log('Processing user creation...');
} catch (error) {
console.error('Error:', error);
throw error;
}
};
3. テスト自動化のベストプラクティス
# テスト実行スクリプト
#!/bin/bash
# ユニットテストの実行
npm test
# ローカルでのAPI統合テスト
sam local start-api &
API_PID=$!
# APIが起動するまで待機
sleep 5
# テストの実行
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","name":"Test User"}'
# クリーンアップ
kill $API_PID
デバッグのためのTips
- 効果的なエラーハンドリング
const createError = (statusCode, message) => ({
statusCode,
body: JSON.stringify({ error: message })
});
const handler = async (event) => {
try {
// バリデーション
if (!event.body) {
return createError(400, 'Request body is required');
}
const { email, name } = JSON.parse(event.body);
if (!email || !name) {
return createError(400, 'Email and name are required');
}
// メイン処理
} catch (error) {
console.error('Error:', error);
return createError(500, 'Internal server error');
}
};
- 環境変数の管理
# env.json
{
"CreateUserFunction": {
"STAGE": "local",
"TABLE_NAME": "local-users-table",
"DEBUG": "true"
}
}
これらの実践的なアプローチを組み合わせることで、効率的なローカル開発環境を構築し、高品質なサーバーレスアプリケーションの開発が可能になります。
実践的なAWS SAM CLIの使用方法
実運用環境でのAWS SAM CLIの活用方法について、CI/CD、デプロイメント、セキュリティの観点から解説します。
CI/CDパイプラインとの連携方法
1. GitHub Actionsを使用したCI/CD構築
# .github/workflows/sam-deploy.yml
name: Deploy SAM Application
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Setup AWS SAM CLI
uses: aws-actions/setup-sam@v1
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: SAM Build
run: sam build
- name: Run Tests
run: |
pip install pytest
python -m pytest tests/
- name: SAM Deploy
if: github.ref == 'refs/heads/main'
run: |
sam deploy --no-confirm-changeset \
--stack-name prod-stack \
--s3-bucket deployment-artifacts \
--capabilities CAPABILITY_IAM
2. AWS CodePipelineとの統合
# template.yaml内にCodePipelineの定義を追加
Resources:
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
RoleArn: !GetAtt CodePipelineServiceRole.Arn
Stages:
- Name: Source
Actions:
- Name: Source
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
Configuration:
RepositoryName: !Ref RepositoryName
BranchName: main
OutputArtifacts:
- Name: SourceCode
- Name: Build
Actions:
- Name: Build
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
Configuration:
ProjectName: !Ref BuildProject
InputArtifacts:
- Name: SourceCode
OutputArtifacts:
- Name: BuildOutput
本番環境へのデプロイメントフロー
1. 段階的デプロイメント戦略
# 開発環境へのデプロイ sam deploy --stack-name dev-stack \ --parameter-overrides Stage=dev \ --tags Environment=Development # ステージング環境へのデプロイ sam deploy --stack-name stg-stack \ --parameter-overrides Stage=stg \ --tags Environment=Staging # 本番環境へのデプロイ sam deploy --stack-name prod-stack \ --parameter-overrides Stage=prod \ --tags Environment=Production \ --no-execute-changeset # 変更セットの確認用
2. ロールバック戦略の実装
# template.yamlでのデプロイメント設定
Globals:
Function:
AutoPublishAlias: live
DeploymentPreference:
Type: Linear10PercentEvery10Minutes
Alarms:
- !Ref AliasErrorMetricGreaterThanZeroAlarm
- !Ref LatencyAlarm
Resources:
AliasErrorMetricGreaterThanZeroAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Lambda Function Error > 0
ComparisonOperator: GreaterThanThreshold
EvaluationPeriods: 2
MetricName: Errors
Namespace: AWS/Lambda
Period: 300
Statistic: Sum
Threshold: 0
セキュリティベストプラクティスの実装
1. IAMポリシーの最小権限原則
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
Policies:
- Statement:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
Resource: !GetAtt MyTable.Arn
Condition:
StringEquals:
'aws:RequestTag/Environment': !Ref Environment
2. セキュリティ設定の自動チェック
# AWS Config Ruleの設定
Resources:
LambdaFunctionSettingsRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: lambda-function-settings-check
Source:
Owner: AWS
SourceIdentifier: LAMBDA_FUNCTION_SETTINGS_CHECK
Scope:
ComplianceResourceTypes:
- AWS::Lambda::Function
InputParameters:
runtime: nodejs18.x
timeout: 30
memorySize: 128
3. 機密情報の安全な管理
# AWS Systems Managerパラメータストアの使用
aws ssm put-parameter \
--name "/myapp/prod/db-password" \
--value "mypassword" \
--type SecureString
# SAMテンプレートでの参照
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
DB_PASSWORD: !Sub '{{resolve:ssm:/myapp/${Stage}/db-password:1}}'
4. セキュリティモニタリングの実装
Resources:
SecurityLogGroup:
Type: AWS::Logs::LogGroup
Properties:
RetentionInDays: 14
SecurityAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Security violation alarm
MetricName: SecurityViolations
Namespace: Custom/Security
ComparisonOperator: GreaterThanThreshold
EvaluationPeriods: 1
Period: 300
Statistic: Sum
Threshold: 0
TreatMissingData: notBreaching
これらの実践的なアプローチを組み合わせることで、セキュアで効率的な本番環境の運用が可能になります。特に、CI/CDパイプラインの自動化、段階的なデプロイメント戦略、そしてセキュリティベストプラクティスの実装は、安定したサーバーレスアプリケーションの運用に不可欠です。
AWS SAM CLI を使用した開発効率化テクニック
実践的な開発効率化テクニックと、実際のプロジェクトでの活用事例を紹介します。
開発生産性を3倍にする自動化スクリプト集
1. デプロイメント自動化スクリプト
#!/bin/bash
# deploy.sh - 環境別デプロイメントスクリプト
# 設定値
STACK_NAME_PREFIX="my-serverless-app"
S3_BUCKET="my-deployment-artifacts"
REGION="ap-northeast-1"
# 引数チェック
if [ -z "$1" ]; then
echo "Usage: ./deploy.sh <environment>"
exit 1
fi
ENV=$1
STACK_NAME="${STACK_NAME_PREFIX}-${ENV}"
# ビルドとテスト
echo "Building and testing..."
sam build || exit 1
npm test || exit 1
# デプロイ
echo "Deploying to ${ENV} environment..."
sam deploy \
--stack-name ${STACK_NAME} \
--s3-bucket ${S3_BUCKET} \
--parameter-overrides \
Environment=${ENV} \
Stage=${ENV} \
--capabilities CAPABILITY_IAM \
--region ${REGION} \
--no-fail-on-empty-changeset \
--tags Environment=${ENV}
2. Lambda関数のボイラープレート生成スクリプト
# generate_function.py
import os
import sys
from typing import Dict, Any
def create_function_template(name: str, api_path: str) -> Dict[str, Any]:
return {
"handler": f"src/handlers/{name}/index.handler",
"template": f"""
# src/handlers/{name}/index.js
const handler = async (event) => {{
try {{
const response = {{
statusCode: 200,
body: JSON.stringify({{
message: "Success"
}})
}};
return response;
}} catch (error) {{
console.error('Error:', error);
return {{
statusCode: 500,
body: JSON.stringify({{ error: "Internal Server Error" }})
}};
}}
}};
exports.handler = handler;
""",
"test": f"""
# tests/unit/{name}.test.js
const {{ handler }} = require('../../src/handlers/{name}');
describe('{name} Lambda', () => {{
it('should return success response', async () => {{
const event = {{}};
const result = await handler(event);
expect(result.statusCode).toBe(200);
}});
}});
""",
"sam_template": f"""
{name}Function:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/{name}/index.handler
Runtime: nodejs18.x
Events:
ApiEvent:
Type: Api
Properties:
Path: {api_path}
Method: post
"""
}
def main(function_name: str, api_path: str):
template = create_function_template(function_name, api_path)
# ディレクトリ作成
os.makedirs(f"src/handlers/{function_name}", exist_ok=True)
os.makedirs(f"tests/unit", exist_ok=True)
# ファイル生成
with open(f"src/handlers/{function_name}/index.js", "w") as f:
f.write(template["template"])
with open(f"tests/unit/{function_name}.test.js", "w") as f:
f.write(template["test"])
print(f"SAMテンプレートに追加するコード:\n{template['sam_template']}")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python generate_function.py <function_name> <api_path>")
sys.exit(1)
main(sys.argv[1], sys.argv[2])
コスト最適化のためのベストプラクティス
1. リソース使用効率の最適化
# template.yaml
Globals:
Function:
# メモリサイズの最適化
MemorySize: 128
# タイムアウトの適切な設定
Timeout: 6
# 同時実行数の制限
ReservedConcurrentExecutions: 100
Resources:
OptimizedFunction:
Type: AWS::Serverless::Function
Properties:
# Provisioned Concurrencyの設定
ProvisionedConcurrencyConfig:
ProvisionedConcurrentExecutions: 5
# レイヤーの活用
Layers:
- !Ref CommonLibsLayer
2. コストモニタリングの設定
Resources:
CostAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub ${AWS::StackName}-CostAlarm
AlarmDescription: Daily cost exceeded threshold
MetricName: EstimatedCharges
Namespace: AWS/Billing
Statistic: Maximum
Period: 21600 # 6時間
EvaluationPeriods: 1
Threshold: 10 # 10ドル
ComparisonOperator: GreaterThanThreshold
AlarmActions:
- !Ref AlertTopic
大規模プロジェクトでの活用事例
1. マイクロサービスアーキテクチャの実装例
# 複数のマイクロサービスを管理するSAMテンプレート
Resources:
# ユーザーサービス
UserService:
Type: AWS::Serverless::Application
Properties:
Location: ./services/user-service/template.yaml
Parameters:
Environment: !Ref Environment
# 注文サービス
OrderService:
Type: AWS::Serverless::Application
Properties:
Location: ./services/order-service/template.yaml
Parameters:
Environment: !Ref Environment
# 決済サービス
PaymentService:
Type: AWS::Serverless::Application
Properties:
Location: ./services/payment-service/template.yaml
Parameters:
Environment: !Ref Environment
2. 開発チームでの効率的な協業方法
# プロジェクト構造
project/
├── services/
│ ├── user-service/
│ │ ├── template.yaml
│ │ └── src/
│ ├── order-service/
│ │ ├── template.yaml
│ │ └── src/
│ └── payment-service/
│ ├── template.yaml
│ └── src/
├── layers/
│ └── common/
├── scripts/
│ ├── deploy.sh
│ └── generate_function.py
└── template.yaml
# チーム開発用のMakefileの例
Makefile:
make install:
npm install
make test:
npm test
make lint:
eslint .
make build:
sam build
make deploy-dev:
./scripts/deploy.sh dev
make deploy-prod:
./scripts/deploy.sh prod
3. パフォーマンス最適化の実例
// Lambda関数の最適化例
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();
// コネクションの再利用
const ddbClient = new AWS.DynamoDB.DocumentClient({
maxRetries: 3,
httpOptions: {
timeout: 5000,
connectTimeout: 3000
}
});
// バッチ処理の最適化
const processBatch = async (items) => {
const batchSize = 25; // DynamoDBの制限
const batches = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
batches.push(batch);
}
const promises = batches.map(async (batch) => {
const params = {
RequestItems: {
'TableName': batch.map(item => ({
PutRequest: {
Item: item
}
}))
}
};
return ddbClient.batchWrite(params).promise();
});
await Promise.all(promises);
};
これらの効率化テクニックを適切に組み合わせることで、開発速度の向上、運用コストの削減、そしてプロジェクト全体の品質向上を実現できます。特に大規模プロジェクトでは、自動化スクリプトやベストプラクティスの活用が重要です。