はじめに
AWS Lambdaは、サーバーの管理不要でコードを実行できるサーバーレスコンピューティングサービスとして広く利用されています。2020年12月からは、Lambda上でDockerコンテナを実行できるようになり、さらに柔軟なアプリケーション開発が可能になりました。
本記事では、AWS LambdaとDockerを組み合わせたサーバーレスアプリケーションの構築方法について、基礎から実践まで詳しく解説します。
AWS Lambda × Dockerの魅力
従来のLambdaでは、Node.js、Python、Java、Goなどの言語をサポートしていましたが、コンテナイメージのサポートにより、以下のような大きなメリットが生まれました:
- 言語や依存関係の自由度向上:任意の言語やライブラリを利用可能
- 既存のDockerスキルやツールの活用:Docker開発環境をそのまま流用可能
- コンテナサイズの柔軟性:最大10GBのコンテナイメージをサポート
- ローカル開発とテストの容易さ:Dockerを使った開発環境との一貫性
- 既存コンテナアプリケーションのLambda移行:コンテナ化済みアプリの再利用
前提条件
この記事を進めるにあたって、以下のツールが必要です:
- AWSアカウント
- AWS CLI(設定済み)
- Docker
- エディタ(VSCode等)
Lambda用Dockerイメージの基本
Lambda用のDockerイメージには以下の2つの選択肢があります:
- AWS提供のベースイメージを使用する:Lambda実行環境に最適化されたイメージ
- カスタムイメージを作成する:Lambda Runtime API互換のイメージを自作
初めての方は、AWS提供のベースイメージを使うのがおすすめです。ここでは、Python用のベースイメージを使った例を紹介します。
実践編:Dockerイメージを使ったLambda関数の構築
手順1:プロジェクト構成の作成
まず、プロジェクトディレクトリを作成します:
mkdir lambda-docker-demo
cd lambda-docker-demo
以下のファイル構成で進めていきます:
lambda-docker-demo/
├── app.py # Lambdaハンドラーコード
├── Dockerfile # Dockerイメージ定義
├── requirements.txt # Pythonの依存関係
└── deploy.sh # デプロイスクリプト
手順2:アプリケーションコードの作成
シンプルなPythonアプリケーションを作成します。app.py
に以下のコードを記述します:
import json
import requests
from datetime import datetime
def handler(event, context):
"""サンプルLambda関数"""
# 外部APIからデータ取得のサンプル
try:
response = requests.get('https://api.ipify.org?format=json', timeout=3)
ip_data = response.json()
ip_address = ip_data['ip']
except Exception as e:
ip_address = f"APIリクエストエラー: {str(e)}"
# 現在時刻の取得
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# イベント情報の取得
path = event.get('path', 'パスなし')
method = event.get('httpMethod', 'メソッドなし')
headers = event.get('headers', {})
query_params = event.get('queryStringParameters', {})
# レスポンスの構築
result = {
'message': 'AWS Lambda with Docker',
'timestamp': current_time,
'serverIp': ip_address,
'request': {
'path': path,
'method': method,
'userAgent': headers.get('User-Agent', 'Unknown'),
'params': query_params
}
}
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json'
},
'body': json.dumps(result, ensure_ascii=False)
}
requirements.txt
ファイルに依存関係を記述します:
requests==2.28.1
手順3:Dockerfileの作成
次に、Lambdaでコンテナを実行するためのDockerfileを作成します:
# AWS提供のLambda Python 3.9ベースイメージを使用
FROM public.ecr.aws/lambda/python:3.9
# 作業ディレクトリを/varに設定
WORKDIR ${LAMBDA_TASK_ROOT}
# 依存関係ファイルをコピー
COPY requirements.txt .
# 依存関係のインストール
RUN pip install -r requirements.txt
# アプリケーションコードをコピー
COPY app.py .
# Lambdaハンドラーを設定
CMD [ "app.handler" ]
手順4:Dockerイメージのビルド
ローカルでDockerイメージをビルドします:
docker build -t lambda-docker-demo .
手順5:ローカルでのテスト
Lambda実行環境をエミュレートするために、dockerコマンドでコンテナを実行し、テストリクエストを送信できます:
# Lambda実行環境のエミュレーション
docker run -p 9000:8080 lambda-docker-demo
# 別のターミナルでテストリクエストを送信
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{
"path": "/test",
"httpMethod": "GET",
"headers": {"User-Agent": "curl/test"},
"queryStringParameters": {"param1": "value1"}
}'
手順6:Amazon ECRにイメージをプッシュ
Lambda関数でコンテナイメージを使用するには、まずAmazon ECR(Elastic Container Registry)にイメージをプッシュする必要があります:
# ECRリポジトリの作成
aws ecr create-repository --repository-name lambda-docker-demo --region ap-northeast-1
# ECRへのログイン
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com
# イメージにタグ付け
docker tag lambda-docker-demo:latest <アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-docker-demo:latest
# ECRへのプッシュ
docker push <アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-docker-demo:latest
手順7:Lambda関数の作成
AWS CLIを使用してLambda関数を作成します:
aws lambda create-function \
--function-name lambda-docker-function \
--package-type Image \
--code ImageUri=<アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-docker-demo:latest \
--role arn:aws:iam::<アカウントID>:role/lambda-execution-role \
--region ap-northeast-1
注意: lambda-execution-role
は事前に作成しておく必要があります。基本的なLambda実行ロールにはAWSLambdaBasicExecutionRole
ポリシーがアタッチされている必要があります。
手順8:Lambda関数のテスト
AWS CLIまたはAWSコンソールからLambda関数をテストできます:
AWS CLIの場合:
aws lambda invoke \
--function-name lambda-docker-function \
--payload '{"path": "/test", "httpMethod": "GET", "headers": {"User-Agent": "aws-cli"}, "queryStringParameters": {"param1": "value1"}}' \
--region ap-northeast-1 \
response.json
cat response.json
Lambda × Dockerの実践的なユースケース
1. カスタムランタイムを使用したアプリケーション
Lambda標準環境では対応していない言語(RustやC++など)や、特定のバージョンが必要な場合にDockerイメージを活用できます。
Rustの例(Dockerfile):
FROM rust:1.53 as builder
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release
FROM public.ecr.aws/lambda/provided:al2
COPY --from=builder /usr/src/app/target/release/lambda-rust-app /var/task/bootstrap
CMD [ "bootstrap" ]
2. 大きな依存関係を持つアプリケーション
機械学習モデルや大規模なライブラリを含むアプリケーションもDockerイメージで簡単にパッケージ化できます。
機械学習モデルの例(Dockerfile):
FROM public.ecr.aws/lambda/python:3.9
# 依存関係のインストール
COPY requirements.txt .
RUN pip install -r requirements.txt
# モデルファイルをコピー
COPY ./model /var/task/model
COPY app.py .
CMD [ "app.handler" ]
3. マイクロサービスとしてのAPI実装
API Gateway、Lambda、Dockerを組み合わせて、フルマネージドなマイクロサービスAPIを構築できます。
以下のAWS CLIコマンドでAPI Gatewayと連携できます:
# Lambda関数のリソースベースのポリシー追加
aws lambda add-permission \
--function-name lambda-docker-function \
--statement-id apigateway \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:<リージョン>:<アカウントID>:<API ID>/*/*/*"
# API Gatewayの作成コマンド(概要)
aws apigateway create-rest-api --name lambda-docker-api
# リソースやメソッドの設定
# ...
# デプロイ
aws apigateway create-deployment --rest-api-id <API ID> --stage-name prod
パフォーマンス最適化のヒント
Lambda×Dockerを使用する際のパフォーマンス最適化について、いくつかのヒントを紹介します:
1. イメージサイズの最適化
- マルチステージビルドを活用する
- 不要なファイルを含めない
- Alpine LinuxベースのイメージやDistrolessイメージを検討
最適化したDockerfileの例:
FROM public.ecr.aws/lambda/python:3.9-slim as builder
WORKDIR /var/task
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -t python/
FROM public.ecr.aws/lambda/python:3.9-slim
WORKDIR ${LAMBDA_TASK_ROOT}
COPY --from=builder /var/task/python ./
COPY app.py .
CMD [ "app.handler" ]
2. コールドスタート時間の短縮
- 依存関係を最小限に保つ
- 初期化コードを最適化する
- Provisioned Concurrencyを活用する
3. ローカル開発環境の整備
AWS SAM(Serverless Application Model)CLIを使用して、ローカル環境でLambda関数をテストできます:
# template.yamlの例
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
DockerFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
ImageUri: lambda-docker-demo:latest
Events:
ApiEvent:
Type: Api
Properties:
Path: /test
Method: GET
# ローカル実行
sam local start-api
本番運用のベストプラクティス
1. CIパイプラインの構築
GitHub ActionsやAWS CodePipelineを使用して、継続的なビルドとデプロイを自動化できます:
GitHub Actionsの例(.github/workflows/deploy.yml):
name: Deploy Lambda Docker
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- 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: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build and push image to ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: lambda-docker-demo
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:${{ github.sha }} .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:${{ github.sha }}
- name: Update Lambda Function
run: |
aws lambda update-function-code \
--function-name lambda-docker-function \
--image-uri ${{ steps.login-ecr.outputs.registry }}/lambda-docker-demo:${{ github.sha }}
2. モニタリングとログ管理
CloudWatchとX-Ray統合で、Lambda関数のパフォーマンスと問題を追跡できます:
# X-Ray統合の例(app.pyに追加)
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all
patch_all()
def handler(event, context):
# 関数の処理
...
依存関係にX-Rayを追加:
aws-xray-sdk==2.11.0
3. セキュリティ対策
- ECRイメージスキャンを有効化
- 最小権限の原則に従ったIAMロールの設定
- 機密情報はAWS Systems Manager Parameter StoreやSecrets Managerで管理
# ECRイメージスキャンの有効化
aws ecr put-image-scanning-configuration \
--repository-name lambda-docker-demo \
--image-scanning-configuration scanOnPush=true \
--region ap-northeast-1
Lambda×Dockerの制限事項と注意点
- イメージサイズ制限: 最大10GBまで(解凍後)
- 実行時間制限: 最大15分(通常のLambdaと同じ)
- メモリ設定: 最大10,240MB
- コールドスタート: コンテナイメージはZIP形式のデプロイよりも起動時間が長くなる傾向がある
- 料金: 実行時間とメモリ使用量に基づく(通常のLambdaと同じ課金モデル)
まとめ
AWS LambdaとDockerの組み合わせにより、サーバーレスコンピューティングの柔軟性と開発の容易さが大きく向上しました。本記事では、基本的なセットアップから本番運用のベストプラクティスまで、Lambda×Dockerを活用したサーバーレスアプリケーション構築について解説しました。
この技術を活用することで、特定の言語やライブラリに縛られることなく、幅広いアプリケーションをサーバーレスアーキテクチャで実現できます。また、既存のDockerベースの開発フローを活かして、スムーズにサーバーレス環境へ移行することも可能です。
Lambda×Dockerの組み合わせは、特に以下のようなケースで威力を発揮します:
- カスタム依存関係や特殊なランタイムが必要なアプリケーション
- 既存のコンテナ化されたアプリケーションのサーバーレス化
- 複雑な設定や大規模なライブラリを含むアプリケーション
最後に、AWS Lambda×Dockerは比較的新しい技術であり、今後も進化していくことが期待されます。公式ドキュメントを定期的にチェックして、最新情報を入手することをお勧めします。
コメント