1. この記事について

AWS Lambda は 2020 年末にコンテナイメージのサポートを GA し、ZIP デプロイの 250MB (展開後) 上限を超える 10GB のイメージサイズ、任意のベース OCI イメージ、multi-arch (arm64 / x86_64) ビルドといった大幅な拡張を手に入れた。しかし本番運用の現場では「ZIP のままで十分か、Container image に切り替えるべきか」「Dockerfile の multi-stage / multi-arch をどう組むべきか」「Lambda Web Adapter で既存の HTTP サーバーを Lambda 化する黄金パターンは何か」「cold start を実用域に持ち込む 5 つの最適化レバーは何か」といった判断が散在情報のまま放置されがちである。
本記事はその空白を 1 本で解消する。ZIP との 5 軸比較から始まり、multi-stage / multi-arch Dockerfile の完全実装、ECR push pipeline (CodeBuild + GitHub Actions OIDC 両構成)、Lambda Web Adapter による既存資産の Lambda 化、cold start 最適化までを Terraform 完全 HCL 付きで解説する。読者が「そのままコピー&ペーストで本番 Container image Lambda を構築できる」ことをゴールとしている。
- Vol1 (本記事): Container image Lambda 本番運用完全ガイド — 10GB イメージ活用 / multi-arch / Lambda Web Adapter / ECR push pipeline / cold start 最適化を1本で完走
- Vol2: SnapStart 完全活用編 — JVM / Python / Node ランタイムの cold start を ms 単位に圧縮する SnapStart の本番設計
- Vol3: Powertools + Layers 統合運用編 — observability / parameter / idempotency の標準化と Layers 配布戦略 (準備中)
- ZIP デプロイの Lambda を本番運用しており、Container image への移行/併用を検討しているサーバーサイドエンジニア
- 既存の Express / FastAPI / Spring Boot 等の HTTP サーバー資産を Lambda に載せたいアーキテクト
- multi-arch (arm64 + x86_64) 対応や 10GB 上限の活用、cold start 最適化を体系的に押さえたい中級者
1-1. なぜ今 Container image Lambda か
Container image Lambda が 2020 年末に GA してから 5 年以上が経過したが、日本語記事には依然として 4 つの空白がある。
空白①: ZIP との横断比較が不足している
Container image の単独入門記事は増えたが、「サイズ上限 / cold start / デプロイ速度 / ユースケース / コスト」の 5 軸で ZIP と公平比較し、移行判断フローまで提示した記事はほぼ存在しない。本記事§3 でこの空白を埋める。
空白②: multi-stage + multi-arch Dockerfile の実例が散在
Dockerfile multi-stage build の Lambda 適用例、TARGETPLATFORM を活用した multi-arch ビルド、AWS 提供 base image と任意 OCI image の選定マトリクスを 1 章にまとめた記事が見当たらない。本記事§4 で完全実装を示す。
空白③: Lambda Web Adapter の挙動解剖がない
LWA (Lambda Web Adapter) は既存 HTTP サーバーをほぼ無改修で Lambda 化できる強力な仕組みだが、内部経路 (HTTP Request → LWA Extension → 内部 App Server) を解剖した記事が国内には少ない。本記事§6 でこの解剖を行う。
空白④: cold start 最適化の 5 レバー俯瞰がない
provisioned concurrency / image size 削減 / init phase 短縮 / arm64 採用 / SnapStart (Vol2 予告) の 5 つの最適化レバーを 1 枚の戦略マップで提示した記事がほぼ存在しない。本記事§7 で俯瞰図を提供する。
1-2. 本記事のゴール
本記事を読み終えると以下を単独で実施できる。
| ゴール | 対応章 |
|---|---|
| ZIP Lambda と Container image Lambda の選定判断 (5 軸比較) | §3 |
| multi-stage / multi-arch Dockerfile の Terraform 統合実装 | §4 |
| ECR push pipeline (CodeBuild + GHA OIDC 両構成) の本番構築 | §5 |
| Lambda Web Adapter による既存 HTTP サーバーの Lambda 化 | §6 |
| Container image Lambda の cold start 最適化 5 レバー実装 | §7 |
| 落とし穴 10 選を回避した本番投入 | §8 |
本記事は §3〜§7 の各章が独立して完結する構成のため、目的に応じた読み方ができる。
- 移行判断のみ: §3 の ZIP 比較 + 移行判断フローを読む
- Dockerfile 実装のみ: §4 の multi-stage / multi-arch 実装を参照する
- CI/CD パイプライン構築: §5 の ECR push pipeline (CodeBuild / GHA OIDC) を構築する
- 既存 HTTP サーバーの Lambda 化: §6 の Lambda Web Adapter 解剖を読む
- cold start 対策: §7 の 5 レバー最適化を実施する
通読する場合は §3 → §4 → §5 → §6 → §7 の順が推奨である。各章は前章の知識を前提とせずに設計しているが、§3 の全体像を把握してから他章に進む方が理解が深まる。
1-3. 差別化6軸
本記事が既存の Container image Lambda 入門記事と明確に差別化される点を 6 軸で整理する。
- 10GB イメージ活用 + multi-arch (arm64/x86_64) 対応を1本で網羅
国内記事の多くは ZIP からの移行入門にとどまる。本記事は 10GB イメージを活かした大規模 ML 推論・FFmpeg・OCR 等の重量ワークロードと、docker buildx + TARGETPLATFORM を用いた multi-arch manifest による arm64 / x86_64 同時配布を §4-§5 で完全実装する。 - Lambda Web Adapter (LWA) による既存 HTTP サーバーのサーバーレス化を詳解
Express / FastAPI / Spring Boot 等の既存 HTTP サーバー資産をほぼ無改修で Lambda 化できる LWA の内部経路 (HTTP Request → LWA Extension → 内部 App Server) を §6 で徹底解剖する。LWA を含む統合解説は国内記事でも希少である。 - ZIP Lambda との選択軸・移行判断フローを提供
サイズ上限 / cold start / デプロイ速度 / ユースケース / コストの 5 軸比較マトリクスと移行判断ツリーを §3 に掲載する。「移行すべきか・ZIP のまま継続すべきか・用途別に併用すべきか」を読者が自己判断できる構成とした。 - cold start 最適化のロードマップ (Vol1 → Vol2 SnapStart)
provisioned concurrency / image size 削減 / init phase 短縮 / arm64 採用 / SnapStart (Vol2 予告) の 5 レバーを §7 で俯瞰し、Vol2 (SnapStart 完全活用編) への橋渡しを行う。cold start を実用域に収める段階的な最適化ロードマップを提示する。 - Terraform + AWS CLI + コンソール 3 点セット完走
§4〜§7 の全章を Terraform HCL 完全実装・AWS CLI コマンド・コンソール操作の 3 形式で提供する。コマンドはそのままコピー&ペーストで動くレベルの精度で掲載し、「本番投入できる」を担保する。 - シリーズナビ ep-box による Vol1-3 全体案内 + Vol2 予告 ep-btn
§1 冒頭と §8 末尾の 2 箇所にシリーズナビ ep-box を配置し、Lambda 応用シリーズ全 3 巻 (Vol1 Container image / Vol2 SnapStart / Vol3 Powertools) の全体像を案内する。読者が目的のトピックに最短でたどり着けるよう導線を整備した。
1-4. 章立て
本記事の全体構成と各章の目的を以下に示す。
| §N | タイトル | 概要 |
|---|---|---|
| §1 | この記事について | 差別化6軸・本記事のゴール・想定環境 |
| §2 | 前提・環境・準備 | 必要ツール・バージョン・IAM・ゴール状態の定義 |
| §3 | Container image Lambda 全体像 + ZIP との比較 | 5 軸比較 + 移行判断フロー + 全体アーキテクチャ |
| §4 | Dockerfile 完全解説 | multi-stage / multi-arch / base image 選定 |
| §5 | ECR push pipeline + Lambda 更新 | CodeBuild + GHA OIDC 両構成 Terraform |
| §6 | Lambda Web Adapter | HTTP server を Lambda 化する黄金パターン |
| §7 | cold start 最適化 | 5 つの最適化レバー + Vol2 SnapStart 予告 |
| §8 | まとめ + Vol2 予告 + 落とし穴 10 選 | チートシート |
1-5. 想定環境
本記事のサンプルコードは以下の環境で動作検証した。ローカル開発環境は macOS (Apple Silicon) で検証しているが、Windows / Linux でも同一手順で再現できる。
| ツール / サービス | バージョン / 仕様 |
|---|---|
| Terraform | 1.9.x (aws provider 5.x) |
| AWS CLI | v2 (2.15.x 以降推奨) |
| Docker / docker buildx | 最新安定版 (BuildKit 有効) |
| Lambda ランタイム | Python 3.12 / Node.js 20 / Java 21 |
| Amazon ECR | us-east-1 (サンプルリージョン) |
| Lambda Web Adapter | v0.8.x (Lambda Layer 形式) |
| Git | 2.x 以降 |
リージョンはサンプルコード全体を通じて us-east-1 を使用する。別リージョンへ変更する場合は Terraform 変数 aws_region の値を書き換えるだけでよい。IAM 権限の詳細については §2-1 で解説する。
本記事のサンプルは 2026 年 4 月時点の AWS サービス仕様・Terraform プロバイダー (aws provider 5.x) に基づいている。将来的なサービス変更については AWS 公式ドキュメントを参照してほしい。
§3 Container image Lambda 全体像 + ZIP との比較に進む
2. 前提・環境・準備

2-1. 前提環境
本記事を進めるにあたり、以下の環境・権限が整っていることを事前に確認してほしい。
AWS アカウント・IAM 権限
以下の IAM アクションが必要である。最小権限原則に従い、開発者ロールまたは CI/CD ロールに付与する。
| IAM アクション | 用途 |
|---|---|
ecr:CreateRepository ecr:GetAuthorizationToken ecr:BatchCheckLayerAvailability ecr:PutImage ecr:InitiateLayerUpload ecr:UploadLayerPart ecr:CompleteLayerUpload | ECR リポジトリ作成・イメージ push |
lambda:CreateFunction lambda:UpdateFunctionCode lambda:UpdateFunctionConfiguration lambda:GetFunctionConfiguration | Lambda 関数のデプロイ・設定変更 |
codebuild:CreateProject codebuild:StartBuild | ECR push pipeline (CodeBuild) 操作 |
s3:PutObject s3:GetObject | CodeBuild アーティファクト保管 |
iam:PassRole | Lambda 実行ロール・CodeBuild ロールの付与 |
ローカル開発環境
| ツール | 最低バージョン | インストール確認コマンド |
|---|---|---|
| Docker / docker buildx | 最新安定版 (BuildKit 有効) | docker buildx version |
| AWS CLI | v2 (2.15.x 以降) | aws --version |
| Terraform | 1.9.x | terraform version |
| Git | 2.x 以降 | git --version |
想定リージョンは us-east-1 である。別リージョンを使用する場合、§3 以降の Terraform コードの aws_region 変数を変更すること。
2-2. 使用技術スタック
本記事で使用するサービス・ライブラリを以下にまとめる。
| カテゴリ | サービス / ライブラリ | 概要 |
|---|---|---|
| コンピュート | Lambda (package_type=Image) | Container image 形式の Lambda 実行環境 |
| レジストリ | Amazon ECR | OCI コンテナイメージの格納・管理 |
| ビルド | Docker BuildKit / buildx | multi-arch イメージのビルド・キャッシュ最適化 |
| CI/CD (クラウド) | AWS CodeBuild | ECR への自動 push pipeline (AWS ネイティブ) |
| CI/CD (GitHub) | GitHub Actions + OIDC | ECR への自動 push pipeline (OIDC 連携) |
| IaC | Terraform aws provider 5.x | インフラ全体の宣言的管理 |
| HTTP アダプタ | Lambda Web Adapter (LWA) v0.8.x | 既存 HTTP サーバーの Lambda 化 Extension |
| モニタリング | Amazon CloudWatch Logs | Lambda 実行ログの収集・保管 |
| スケーリング | Provisioned Concurrency | cold start 削減のための事前ウォームアップ |
2-3. ゴール状態の定義
本記事を完走した時点で、以下の成果物が構築・検証済みとなる。
- Terraform によりデプロイされた Container image Lambda (
package_type = "Image") - multi-arch (arm64 + x86_64) 対応の ECR リポジトリ + multi-arch manifest list
- ECR push pipeline — CodeBuild パターン または GitHub Actions OIDC パターン (いずれか一方または両方)
- Lambda Web Adapter を組み込んだ HTTP サーバー (Express / FastAPI) の Lambda 化済み実装
- provisioned concurrency 設定による cold start の実用域への最適化
これらはすべて Terraform HCL として再現可能であり、terraform apply 1 コマンドで同等環境を再構築できる状態を担保している。AWS CLI での等価コマンドおよびコンソール操作手順も各章に併記する。各成果物の Terraform state は独立しており、部分的な適用や破棄も容易に行える。
2-4. 用語整理
本記事で頻繁に登場する用語を事前に整理する。
| 用語 | 説明 |
|---|---|
| Container image Lambda | package_type = "Image" で設定される Lambda デプロイ形式。OCI 準拠コンテナイメージを ECR に push し Lambda 関数として実行する。 |
| OCI (Open Container Initiative) | コンテナイメージ形式の業界標準規格。Docker image は OCI 準拠であり ECR で保管・配布できる。 |
| multi-arch | 1 つのイメージタグで arm64 (Graviton) と x86_64 の両 CPU アーキテクチャに対応する multi-platform manifest list を使う構成。 |
| TARGETPLATFORM | docker buildx build --platform で渡されるビルドターゲット情報 (linux/amd64 / linux/arm64)。Dockerfile 内で ARG TARGETPLATFORM として参照できる。 |
| BuildKit | Docker の次世代ビルドエンジン。並列ビルド・キャッシュマウント・multi-arch ビルドを高速化する。DOCKER_BUILDKIT=1 または docker buildx で有効になる。 |
| LWA (Lambda Web Adapter) | AWS が OSS で提供する Lambda Extension。HTTP リクエストを Lambda イベントに変換し、内部で起動した HTTP サーバーへプロキシする。既存の Express / FastAPI / Spring Boot 等をほぼ無改修で Lambda 化できる。 |
| cold start | Lambda がコールドな状態 (インスタンス非起動) で初回リクエストを受けた際に発生する初期化遅延。Container image は ZIP より init 時間が長くなりやすい。 |
| init phase | cold start の初期化フェーズ。ランタイム起動・ハンドラのインポート・グローバル変数の初期化が含まれる。この時間を短縮することが cold start 最適化の核心となる。 |
| provisioned concurrency | あらかじめ指定数の Lambda インスタンスをウォームアップした状態で待機させる設定。cold start を排除できる一方、常時コストが発生する。 |
以上の用語の詳細な動作原理は各章の該当セクションで解説する。
3. Container image Lambda 全体像 + ZIP との比較
Lambda のデプロイ形式には ZIP パッケージと Container image の 2 種類がある。ZIP は軽量・高速で多くのユースケースに適するが、250MB 制限を超える ML ライブラリや既存 Docker 資産を活用したい場合は Container image が唯一の選択肢となる。本章では全体アーキテクチャ、5 軸比較、移行判断フロー、採用を避けるべきケースを順に整理する。
3-1. Container image Lambda の全体アーキテクチャ
Container image Lambda の基本フローは「ECR にイメージを push し、Lambda がそのイメージ URI を参照する」という構造である。デプロイパイプラインの実態を順に追う。
ECR リポジトリのセットアップ
デプロイ前に ECR リポジトリを作成し、イミュータブルタグを有効化する。
aws ecr create-repository--repository-name myapp--image-tag-mutability IMMUTABLE--image-scanning-configuration scanOnPush=true--region ap-northeast-1
--image-tag-mutability IMMUTABLE を設定することで、既存タグへの上書きを防止し、デプロイの再現性が保証される。scanOnPush=true は ECR へのプッシュ時に Amazon Inspector による脆弱性スキャンを自動実行する設定である。
ビルドとプッシュ
ECR へのイメージ push は次の 3 ステップで完結する。
# 1. イメージのビルド
docker build --platform linux/amd64 -t myapp:v1.0.0 .
# 2. ECR への認証
aws ecr get-login-password --region ap-northeast-1 \
| docker login --username AWS --password-stdin \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com
# 3. タグ付けとプッシュ
docker tag myapp:v1.0.0 \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:v1.0.0
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:v1.0.0
Lambda 関数の更新
ECR に push 後、Lambda 関数に新しいイメージ URI を適用する。
aws lambda update-function-code \
--function-name my-container-lambda \
--image-uri 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:v1.0.0 \
--region ap-northeast-1
--image-uri には ECR URI またはダイジェスト (@sha256:...) を指定できる。プロダクション環境では可変タグ (latest) を避け、ダイジェスト固定またはイミュータブルタグを使うことが鉄則である。
multi-arch manifest による同時配布
Docker Buildx の --platform オプションと ECR の multi-arch manifest を組み合わせることで、arm64 (Graviton3) と x86_64 の両アーキテクチャを 1 つのリポジトリ・同一タグで管理できる。
docker buildx create --use --name multiarch-builder
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:v1.0.0 \
--push .
ECR は OCI Image Index (manifest list) をネイティブサポートしており、Lambda が pull 時にアーキテクチャを自動判定する。arm64 関数は自動的に arm64 レイヤーを取得するため、1 つの ECR リポジトリで複数アーキテクチャの Lambda を管理できる。Graviton3 (arm64) への段階的移行も ECR リポジトリを変更せずに実施できる。
10GB イメージ上限の活用
Lambda の Container image は圧縮状態で最大 10GB まで対応する。ZIP パッケージの 250MB (展開後) と比べて圧倒的に広い制限である。主な活用ユースケースを示す。
| ユースケース | 代表的な依存 | 推定サイズ |
|---|---|---|
| PyTorch 推論 (CPU) | torch + transformers | 2〜4 GB |
| FFmpeg 動画処理 | ffmpeg binary + ffprobe | 100〜200 MB |
| OCR (Tesseract) | tesseract + language packs | 500 MB〜2 GB |
| Java Spring Boot | JDK + Spring dependencies | 200〜600 MB |
| Node.js + 大規模 npm | node_modules + native addon | 300〜800 MB |
IAM と CloudWatch Logs の構成
Container image Lambda の実行ロールには ECR からイメージを取得するための権限は不要である。Lambda サービス側が ECR に対してイメージ pull を行う際、Lambda 関数の実行ロールではなく AWS 管理のサービスロールが使用される。ただし、ECR リポジトリポリシーで Lambda サービスプリンシパル (lambda.amazonaws.com) に対して次の権限を許可する必要がある。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability"
]
}
]
}
実行ロールに必要な最小権限は通常の Lambda と同じく AWSLambdaBasicExecutionRole (CloudWatch Logs への書き込み) であり、Container image だからといって追加権限が増えるわけではない。
ECR ライフサイクルポリシーの設定
ECR に古いイメージが蓄積するとストレージコストが増加するため、ライフサイクルポリシーで自動削除を設定することを推奨する。
{
"rules": [
{
"rulePriority": 1,
"description": "最新10イメージのみ保持",
"selection": {
"tagStatus": "any",
"countType": "imageCountMoreThan",
"countNumber": 10
},
"action": { "type": "expire" }
}
]
}
- ECR → Lambda update-function-code –image-uri が基本デプロイ経路
- multi-arch manifest で arm64 / x86_64 を 1 リポジトリで管理
- 10GB 上限は ML推論 / 動画処理 / 大規模依存ライブラリに有効
3-2. Container image vs ZIP Lambda 5 軸比較
2 つのデプロイ形式を 5 軸で横断的に比較する。
| 比較軸 | Container image | ZIP Lambda |
|---|---|---|
| サイズ上限 | 10GB (圧縮イメージ) | 250MB (展開後) / 50MB (直接 upload) |
| cold start | やや長い (image pull + init) → provisioned concurrency で実用域 | 安定低 (小さい ZIP は数十 ms) |
| デプロイ速度 | ECR push 込みで 1〜3 分 (CI/CD) | ZIP upload で数十秒 |
| ユースケース | ML推論・大規模依存・既存 Docker アプリの Lambda 化・LWA 活用 | 軽量 API・イベント処理・小規模関数 |
| コスト | ECR ストレージ ($0.10/GB/月) + Lambda 実行費 | Lambda 実行費のみ |
cold start の詳細
Container image Lambda の cold start が長い主な理由はイメージのダウンロードと init フェーズにある。Lambda は内部的にスナップショットキャッシュを活用しているが、イメージサイズが大きいほど init 時間が増加する傾向がある。
| イメージサイズ | cold start 目安 (provisioned なし) | 推奨対策 |
|---|---|---|
| ~100 MB | 1〜2 秒 | 通常許容範囲 |
| 100 MB〜1 GB | 2〜8 秒 | arm64 + 軽量 base image |
| 1 GB〜4 GB | 8〜30 秒 | provisioned concurrency 必須 |
| 4 GB 超 | 30 秒以上の可能性 | タイムアウト設計の見直し必須 |
arm64 (Graviton3) を選択することで x86_64 比でコストが約 20% 削減され、cold start も改善する傾向がある。大規模 ML 推論では arm64 + provisioned concurrency の組み合わせが実績のある構成である。
コスト比較の実例
1 か月あたり 1 GB のイメージを ECR に保存した場合のストレージ費は $0.10 である。1 日あたり 10 万回呼び出す軽量関数 (128 MB / 100 ms) では Lambda 実行費のほうがはるかに大きいため、ECR ストレージコストはほとんどの場合で問題にならない。ただし、50 関数以上でそれぞれ 2 GB 以上のイメージを維持する場合はコストが積み上がるため注意が必要である。
- サイズ: 10GB (Container) vs 250MB (ZIP) — 大規模依存は Container 一択
- cold start: Container は長め → provisioned concurrency + arm64 で実用域へ
- コスト: ECR ストレージ費 (+$0.10/GB/月) が追加。小規模なら ZIP が経済的
3-3. 移行判断フロー
ZIP から Container image への移行を検討する際は、次の判断ツリーを順に確認する。
Q1: 依存ライブラリ込みでパッケージサイズが 200MB を超えるか?
- YES → Container image を強く推奨。ZIP の 250MB 制限に近づくと Layer 管理が複雑化し、ライブラリの追加・更新のたびに容量を意識しなければならない。Container image ならその制約がなくなる。
- NO → Q2 へ進む
Q2: 既存の HTTP サーバーアプリ (Express / FastAPI / Spring Boot / Rails) を Lambda 化したいか?
- YES → LWA (Lambda Web Adapter) × Container image が推奨パターン。LWA はアプリをそのまま Lambda 上で動かすプロキシレイヤーであり、
ENTRYPOINTにアプリサーバーを指定するだけで Lambda として機能する。既存 Dockerfile をほぼそのまま流用できるため、移行コストが極めて低い。 - NO → Q3 へ進む
Q3: multi-arch (arm64 / x86_64) ビルドが必要か、または Dockerfile でビルド環境を統一管理したいか?
- YES → Container image で統一管理。Dockerfile が Single Source of Truth になり、ローカル開発・CI・Lambda デプロイで同一環境を保証できる。
docker buildxによる multi-arch ビルドが ECR と完全に統合されている。 - NO → Q4 へ進む
Q4: Provisioned Concurrency を使用する予定か、または cold start の許容上限が 3 秒以上あるか?
- YES → Container image でも問題なし。Provisioned Concurrency を有効化すれば cold start が実質的になくなり、Container image のサイズに依存する遅延は無視できる。
- NO → Q5 へ進む
Q5: Dockerfile のメンテナンスリソース (CI 整備・セキュリティスキャン) があるか?
- YES → Container image の採用を検討。ECR の脆弱性スキャン (Amazon Inspector) と統合でき、OS レベルのパッケージ管理が可能。
- NO → ZIP Lambda を継続。小規模チームや試作フェーズでは ZIP の方がオーバーヘッドが少ない。
結論: Q1〜Q5 のどれかひとつでも YES があれば Container image の採用を検討する価値がある。特に Q1 (サイズ) と Q2 (LWA) は YES になった時点で Container image が実質的な唯一の選択肢となるケースが多い。
| 判断軸 | 推奨形式 | 決め手 |
|---|---|---|
| サイズ > 200MB | Container image | ZIP 制限回避 |
| HTTP サーバーの Lambda 化 | Container image + LWA | Dockerfile 流用 |
| multi-arch 管理 | Container image | ECR manifest list |
| Provisioned Concurrency あり | Container image | cold start 解消 |
| 軽量関数 + コスト最小 | ZIP Lambda | ECR 費用不要 |
3-4. 採用してはいけないケース
- 極小関数 (依存なし・数 KB): hello-world レベルの関数に Container image を使うと Dockerfile のメンテコストと ECR ストレージ費が無駄になる。ZIP + Lambda Layer で十分。
- cold start がミリ秒単位で厳格かつ Provisioned Concurrency のコストを避けたい場合: イメージサイズが大きいほど cold start が長くなる。コスト制約から Provisioned Concurrency を使えない場合は、ZIP Lambda か Go / Rust による極小イメージ構成を検討する。
- 多数の小規模関数 (50 関数以上) で各イメージが 1 GB 以上ある場合: ECR ストレージ費が月数百ドルに達する可能性がある。共有 base layer 戦略か ZIP への切り戻しを検討。
- Dockerfile メンテナンスリソースがない小規模チーム: OS パッケージの脆弱性対応・base image の定期更新・multi-stage ビルドの保守には継続的な工数が必要。ZIP Lambda の方がインフラ負担が軽い。
4. Dockerfile 完全解説 (multi-stage / multi-arch / base image 選定)

4-1. base image 選定マトリクス
Lambda コンテナイメージの起点となる base image は、用途・セキュリティ要件・サイズ要件によって最適な選択肢が異なる。AWS 提供の base image は Lambda Runtime Interface Client (RIC) と Lambda Runtime Interface Emulator (RIE) を内蔵しており、最小の設定で Lambda 対応コンテナを構築できる。
| base image | 圧縮サイズ目安 | 特徴 | 推奨用途 |
|---|---|---|---|
public.ecr.aws/lambda/python:3.12 | ~150 MB | AWS 最適化・Lambda Runtime API 内蔵 | 新規 Python Lambda 開発 |
public.ecr.aws/lambda/nodejs:20 | ~160 MB | Node.js Lambda 最適化・NPM 付属 | Node.js Lambda |
public.ecr.aws/lambda/java:21 | ~300 MB | Java 21 Corretto ベース | Java/Kotlin Lambda |
public.ecr.aws/lambda/dotnet:8 | ~250 MB | .NET 8 ランタイム内蔵 | C#/.NET Lambda |
alpine:3.19 + custom RIC | ~5 MB〜 | 最小サイズ・手動設定要 | 依存を極小化したい上級者向け |
gcr.io/distroless/python3-debian12 | ~50 MB〜 | セキュリティ優先・shell なし | セキュリティ要件の厳しい本番環境 |
| 任意 OCI image + Lambda Web Adapter | 任意 | 既存 HTTP サーバー流用可 | 既存アプリの Lambda 移植 |
base image 選定フロー:
- 新規 Lambda 開発かつ AWS 最適化を優先する場合 →
public.ecr.aws/lambda/*を使う - 既存 Docker アプリ (Express / FastAPI 等の HTTP サーバー) を流用する場合 → 任意 OCI + Lambda Web Adapter
- セキュリティ要件が厳しくシェルアクセスを排除したい場合 →
distroless+ custom RIC - イメージサイズを極限まで削減したい上級者向け →
alpine+ 手動 RIC インストール
AWS 提供の base image は定期的にセキュリティパッチが適用されるため、特別な理由がない限り public.ecr.aws/lambda/* を第一選択とすることを推奨する。
4-2. multi-stage Dockerfile 完全実装
multi-stage ビルドとは、1 つの Dockerfile 内で複数の FROM ステージを定義し、ビルド成果物のみを最終ステージにコピーする手法である。ビルドツール・開発依存・キャッシュファイルを最終イメージから完全に排除でき、イメージサイズの大幅削減とセキュリティ向上を同時に達成できる。
Python Lambda の multi-stage 実装例:
# Stage 1: Builder — 依存パッケージを /build/packages にインストール
FROM public.ecr.aws/lambda/python:3.12 AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --target /build/packages -r requirements.txt
# Stage 2: Runtime — builder の成果物のみをコピーしてランタイムイメージを最小化
FROM public.ecr.aws/lambda/python:3.12
WORKDIR ${LAMBDA_TASK_ROOT}
COPY --from=builder /build/packages ./
COPY app/ ./
CMD ["handler.lambda_handler"]
COPY --from=builder によって builder ステージの pip キャッシュ・ビルドツール・中間ファイルを最終イメージに持ち込まない。${LAMBDA_TASK_ROOT} は Lambda base image が定義する環境変数 (/var/task) を指す。
Node.js Lambda の multi-stage 実装例:
# Stage 1: Builder — npm ci で本番依存のみをインストール
FROM public.ecr.aws/lambda/nodejs:20 AS builder
WORKDIR /build
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
# Stage 2: Runtime
FROM public.ecr.aws/lambda/nodejs:20
WORKDIR ${LAMBDA_TASK_ROOT}
COPY --from=builder /build/node_modules ./node_modules
COPY src/ ./
CMD ["index.handler"]
npm ci --omit=dev で devDependencies を除外し、node_modules だけを最終ステージにコピーする。TypeScript プロジェクトでは builder ステージでコンパイルを行い、dist/ のみをコピーするパターンも有効である。
Java Lambda (Maven) の multi-stage 実装例:
# Stage 1: Builder — Maven でビルドして uber-jar を生成
FROM public.ecr.aws/amazonlinux/amazonlinux:2023 AS builder
RUN dnf install -y java-21-amazon-corretto-headless maven && dnf clean all
WORKDIR /build
COPY pom.xml .
COPY src/ ./src/
RUN mvn package -q -DskipTests
# Stage 2: Runtime
FROM public.ecr.aws/lambda/java:21
COPY --from=builder /build/target/function.jar ${LAMBDA_TASK_ROOT}/lib/
CMD ["com.example.Handler::handleRequest"]
Maven のローカルリポジトリ (~/.m2) を builder ステージに閉じ込め、最終イメージには uber-jar のみを配置する。ビルドキャッシュを持ち込まないためイメージサイズが大幅に削減される。
4-3. multi-arch ビルド (TARGETPLATFORM + BuildKit)
AWS Lambda は 2021 年より arm64 (AWS Graviton2) アーキテクチャをサポートしている。Graviton2 ベースの Lambda は x86_64 比で実行コストが約 20% 削減される上、同等のメモリ割当ならば cold start レイテンシも改善されるケースが報告されている。
Docker BuildKit と docker buildx を組み合わせることで、単一の Dockerfile から linux/amd64 と linux/arm64 の両アーキテクチャイメージを同時にビルドし、マルチアーキテクチャマニフェスト (manifest list) として ECR に push できる。manifest list を使えば単一のイメージタグ (例: :latest) で両アーキテクチャに対応でき、デプロイパイプラインを統一できる。
multi-arch 対応 Dockerfile:
# --platform=$BUILDPLATFORM でビルドマシンの native アーキで builder を実行
FROM --platform=$BUILDPLATFORM public.ecr.aws/lambda/python:3.12 AS builder
ARG TARGETPLATFORM
ARG BUILDPLATFORM
WORKDIR /build
COPY requirements.txt .
# native バイナリを含むパッケージは TARGETPLATFORM 向けに wheel を取得
RUN pip install --no-cache-dir \
--platform "${TARGETPLATFORM//\//-}" \
--target /build/packages \
--only-binary :all: \
-r requirements.txt || \
pip install --no-cache-dir --target /build/packages -r requirements.txt
FROM public.ecr.aws/lambda/python:3.12
WORKDIR ${LAMBDA_TASK_ROOT}
COPY --from=builder /build/packages ./
COPY app/ ./
CMD ["handler.lambda_handler"]
$BUILDPLATFORM はビルドを実行するホストのアーキテクチャ (例: linux/amd64)、$TARGETPLATFORM は成果物のターゲットアーキテクチャ (例: linux/arm64) をそれぞれ表す BuildKit 組み込み変数である。--platform=$BUILDPLATFORM を builder ステージに付与することで、クロスコンパイル時もホスト native の実行速度でビルドを行える。
docker buildx によるビルド & ECR push:
# buildx インスタンスの作成 (初回のみ)
docker buildx create --name mybuilder --driver docker-container --use
docker buildx inspect --bootstrap
# ECR ログイン
AWS_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
AWS_REGION=ap-northeast-1
ECR_URI="${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com/my-lambda"
aws ecr get-login-password --region "${AWS_REGION}" | \
docker login --username AWS --password-stdin \
"${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com"
# multi-arch ビルド & push (manifest list として ECR に登録)
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag "${ECR_URI}:latest" \
--push \
.
--push フラグで manifest list が ECR に直接 push され、単一のイメージタグ :latest で両アーキテクチャに対応できる。docker buildx imagetools inspect "${ECR_URI}:latest" で manifest list の内容を確認できる。
Terraform で arm64 Lambda を定義:
resource "aws_lambda_function" "container_lambda" {
function_name = "my-container-lambda"
package_type = "Image"
image_uri = "${aws_ecr_repository.lambda_repo.repository_url}:latest"
role = aws_iam_role.lambda_exec.arn
architectures = ["arm64"]
timeout = 30
memory_size= 512
}
architectures = ["arm64"] を指定することで Lambda が Graviton2 上で実行される。コスト削減が目的の場合、まず arm64 へ切り替えて性能テストを実施し、メモリサイズのチューニングと組み合わせるのが定石である。
- multi-stage: Builder → Runtime の 2 ステージで最終イメージからビルドツールを完全排除
- TARGETPLATFORM: BuildKit 組み込み変数を使い 1 つの Dockerfile で arm64/x86_64 に対応
- base image: AWS 提供
public.ecr.aws/lambda/*が RIC 内蔵で最初の選択肢 - arm64 採用で cold start 改善 + 実行コスト約 20% 削減 (x86_64 比)
4-4. イメージサイズ削減ベストプラクティス
コンテナ Lambda の cold start レイテンシはイメージサイズに強く相関する。ECR からの pull に要する時間がそのままオーバーヘッドとなるため、特に初回呼び出しが重要なユースケース (API Gateway 統合・低頻度バッチ等) ではイメージサイズの最小化が有効な施策となる。
1. multi-stage ビルドの徹底
builder ステージのキャッシュ・中間ファイルを最終イメージに持ち込まない。Python の場合 pip install --target + COPY --from=builder パターンで pip キャッシュを遮断できる。
2. .dockerignore による除外設定
ビルドコンテキストに不要なファイルを含めず、COPY 命令で余分なファイルを取り込まない。
tests/
docs/
*.md
.git/
.github/
__pycache__/
*.pyc
*.pyo
.pytest_cache/
node_modules/
3. pip インストールオプションの最適化
pip install \
--no-cache-dir \
--no-compile \
--target /build/packages \
-r requirements.txt
--no-cache-dir で pip キャッシュをイメージに残さない。--no-compile で .pyc ファイルの生成を抑制する。
4. RUN 命令のレイヤー集約
中間状態のレイヤーを削減するために && でコマンドをチェーンし、クリーンアップまで 1 つの RUN に収める。
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc libpq-dev && \
pip install --no-cache-dir -r requirements.txt && \
apt-get purge -y gcc && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*
5. arm64 (Graviton2) の採用
イメージサイズ自体は x86_64 と同等だが、実行コストが約 20% 削減される。cold start 性能を維持しながらコスト最適化が図れるため、新規 Lambda では arm64 を第一候補とすることを推奨する。
4-5. よくある Dockerfile 設計ミス
ミス 1: Lambda Runtime API を含まない任意 OCI image をそのまま使用
nginx:alpine や python:3.12-slim などの標準 Docker Hub イメージは Lambda Runtime Interface Client (RIC) を内蔵していない。そのままデプロイすると Lambda が Error: fork/exec /lambda-entrypoint.sh: no such file or directory 等のエラーを返す。public.ecr.aws/lambda/* を使うか、カスタムイメージに RIC を手動インストールする必要がある。
# RIC の手動インストール例 (Python)
pip install awslambdaric
ENTRYPOINT ["/usr/local/bin/python", "-m", "awslambdaric"]
ミス 2: CMD の形式誤り
Lambda コンテナは CMD ["handler_module.function_name"] 形式を期待する。シェル形式 CMD python app.py では Lambda が handler を解決できず、500 Internal Server Error が返る。
# NG: シェル形式・HTTP サーバー起動
CMD ["python", "app.py"]
# OK: Lambda handler 形式
CMD ["handler.lambda_handler"]
ミス 3: multi-arch ビルド時の native ライブラリ未対応
numpy / scipy / Pillow 等 C 拡張を含むパッケージを linux/arm64 向けにビルドする際、ビルドホストが linux/amd64 の場合はクロスコンパイルが必要になる。--platform "${TARGETPLATFORM//\//-}" と --only-binary :all: の組み合わせで PyPI の事前ビルド済み wheel を直接取得する方法が最も確実である。wheel が存在しないパッケージは QEMU エミュレーション (docker buildx create --driver docker-container) を利用してネイティブコンパイルする。
5. ECR push pipeline + Lambda 更新

Container Image Lambda のデプロイフローは ECR への image push → Lambda の image URI 更新 の 2 ステップで構成される。push pipeline には AWS ネイティブな CodeBuild パターンと、GitHub Actions + OIDC パターンの 2 択がある。
5-1. ECR repository 作成 (Terraform)
ECR repository は scan_on_push を有効にして脆弱性スキャンを自動化し、lifecycle policy でイメージ枚数を制御する。
resource "aws_ecr_repository" "lambda_repo" {
name = "my-container-lambda"
image_tag_mutability = "MUTABLE"
image_scanning_configuration {
scan_on_push = true
}
encryption_configuration {
encryption_type = "KMS"
kms_key= aws_kms_key.ecr.arn
}
tags = {
Environment = "production"
Project = "container-lambda"
}
}
resource "aws_ecr_lifecycle_policy" "lambda_repo_policy" {
repository = aws_ecr_repository.lambda_repo.name
policy = jsonencode({
rules = [
{
rulePriority = 1
description = "Keep last 10 images"
selection = {
tagStatus= "any"
countType= "imageCountMoreThan"
countNumber = 10
}
action = { type = "expire" }
}
]
})
}
5-2. パターン A: CodeBuild による push pipeline
CodeBuild はビルド環境を AWS 内に閉じられるため、VPC 統合や PrivateLink 経由の ECR アクセスが可能で、プライベートネット環境に適する。
buildspec.yml — multi-arch ビルド (arm64) と Lambda 自動更新:
version: 0.2
phases:
pre_build:
commands:
- aws ecr get-login-password --region $AWS_DEFAULT_REGION |
docker login --username AWS --password-stdin $ECR_REPOSITORY_URI
- docker buildx create --name mybuilder --use --bootstrap
build:
commands:
- |
docker buildx build \
--platform linux/arm64 \
-t $ECR_REPOSITORY_URI:$CODEBUILD_RESOLVED_SOURCE_VERSION \
-t $ECR_REPOSITORY_URI:latest \
--push .
post_build:
commands:
- |
aws lambda update-function-code \
--function-name $LAMBDA_FUNCTION_NAME \
--image-uri $ECR_REPOSITORY_URI:$CODEBUILD_RESOLVED_SOURCE_VERSION
- aws lambda wait function-updated --function-name $LAMBDA_FUNCTION_NAME
Terraform — CodeBuild project と IAM role:
resource "aws_codebuild_project" "lambda_pipeline" {
name= "container-lambda-pipeline"
service_role = aws_iam_role.codebuild_role.arn
environment {
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/standard:7.0"
type= "LINUX_CONTAINER"
privileged_mode = true
environment_variable {
name = "ECR_REPOSITORY_URI"
value = aws_ecr_repository.lambda_repo.repository_url
}
environment_variable {
name = "LAMBDA_FUNCTION_NAME"
value = aws_lambda_function.container_lambda.function_name
}
}
source {
type= "GITHUB"
location = "https://github.com/your-org/your-repo"
buildspec = "buildspec.yml"
}
artifacts { type = "NO_ARTIFACTS" }
}
resource "aws_iam_role" "codebuild_role" {
name= "codebuild-container-lambda-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{ Effect = "Allow"; Principal = { Service = "codebuild.amazonaws.com" }; Action = "sts:AssumeRole" }]
})
}
resource "aws_iam_role_policy_attachment" "codebuild_ecr" {
role = aws_iam_role.codebuild_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser"
}
resource "aws_iam_role_policy" "codebuild_lambda_update" {
role = aws_iam_role.codebuild_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{ Effect = "Allow"; Action = ["lambda:UpdateFunctionCode", "lambda:GetFunctionConfiguration"]; Resource = aws_lambda_function.container_lambda.arn }]
})
}
5-3. パターン B: GitHub Actions + OIDC による push pipeline
GHA OIDC は長期的なアクセスキーを不要にする。aws-actions/configure-aws-credentials が OIDC トークンを取得し、一時クレデンシャルを発行する。
Terraform — OIDC Provider と IAM Role:
resource "aws_iam_openid_connect_provider" "github_actions" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"]
}
resource "aws_iam_role" "github_actions_lambda" {
name = "github-actions-container-lambda"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Federated = aws_iam_openid_connect_provider.github_actions.arn }
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
}
StringLike = {
"token.actions.githubusercontent.com:sub" = "repo:your-org/your-repo:*"
}
}
}]
})
}
resource "aws_iam_role_policy_attachment" "gha_ecr" {
role = aws_iam_role.github_actions_lambda.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser"
}
resource "aws_iam_role_policy" "gha_lambda_update" {
role = aws_iam_role.github_actions_lambda.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{ Effect = "Allow"; Action = ["lambda:UpdateFunctionCode", "lambda:GetFunctionConfiguration"]; Resource = aws_lambda_function.container_lambda.arn }]
})
}
GitHub Actions workflow — ECR push と Lambda 更新:
# .github/workflows/deploy.yml
name: Deploy Container Lambda
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::<ACCOUNT_ID>:role/github-actions-container-lambda
aws-region: us-east-1
- id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker buildx create --use
docker buildx build --platform linux/arm64 \
-t $ECR_REGISTRY/my-container-lambda:$IMAGE_TAG \
-t $ECR_REGISTRY/my-container-lambda:latest --push .
- name: Update Lambda
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
aws lambda update-function-code \
--function-name my-container-lambda \
--image-uri $ECR_REGISTRY/my-container-lambda:$IMAGE_TAG
aws lambda wait function-updated --function-name my-container-lambda
5-4. Lambda 更新 (image-uri 切り替え)
update-function-code は非同期操作のため wait function-updated で完了を待つ。Terraform では image_uri を更新して terraform apply するだけで再デプロイできる。
# image URI 指定で Lambda 更新
aws lambda update-function-code \
--function-name my-container-lambda \
--image-uri <ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/my-container-lambda:v1.2.3
# 更新完了まで待機 (最大 15 分)
aws lambda wait function-updated \
--function-name my-container-lambda
# 更新後の image URI 確認
aws lambda get-function-configuration \
--function-name my-container-lambda \
--query 'Code.ImageUri' --output text
# 動作確認
aws lambda invoke \
--function-name my-container-lambda \
--cli-binary-format raw-in-base64-out \
--payload '{"key": "value"}' \
response.json && cat response.json
5-5. CodeBuild vs GHA OIDC 選定軸
📊 CodeBuild vs GitHub Actions OIDC 選定軸
| 観点 | CodeBuild | GHA OIDC |
|---|---|---|
| 認証方式 | IAM サービスロール (長期) | OIDC 一時クレデンシャル (短命) |
| VPC 統合 | ✅ 対応 (PrivateLink 経由も可) | ❌ パブリックランナーのみ |
| コスト構造 | ビルド分数課金 ($0.005/分) | GitHub Actions 分数 (プラン依存) |
| 監査ログ | CloudWatch Logs に自動出力 | GitHub Actions ログ (90 日保持) |
| AWS 統合 | CodePipeline / EventBridge 連携 | 外部 CI — 追加設定が必要 |
| 推奨ユースケース | VPC 内 ECR / 社内プライベートネット | OSS / GitHub 中心の開発フロー |
セキュリティ重視なら GHA OIDC (アクセスキー不要)、AWS 統合深度重視なら CodeBuild が適する。
6. Lambda Web Adapter (HTTP server を Lambda 化)

6-1. LWA の仕組み
Lambda Web Adapter (LWA) は AWS が提供する Lambda Extension で、既存の HTTP サーバーをほぼ無改修で Lambda 上で動作させる変換レイヤーだ。Express.js・FastAPI・Spring Boot など任意の HTTP フレームワークをそのまま Lambda にリフトして載せられる。
従来、Lambda で HTTP サーバーを動かすには Lambda ハンドラー関数を専用に実装する必要があった。Express や FastAPI で書かれた既存 Web アプリを Lambda 化するには aws-serverless-express のようなラッパーライブラリか、アーキテクチャの全面書き直しが必要だった。LWA はこの課題を Extension レイヤーで解決した。
LWA の内部動作フロー:
Lambda invoke が発生すると、以下の経路でリクエストが処理される。
- API Gateway / Function URL / ALB が Lambda を invoke
- LWA Extension が Lambda イベント (JSON ペイロード) を受信
- LWA がイベントを HTTP Request に変換
- localhost:PORT (デフォルト 8080) で動作する内部 App Server に転送
- App Server が HTTP Response を返却
- LWA が HTTP Response → Lambda レスポンス形式 (JSON) に変換して返す
この変換レイヤーにより、既存コードへの変更は不要だ。必要なのは PORT 環境変数の設定のみ。Lambda Runtime API との通信は LWA が全て処理するため、アプリ側は通常の HTTP サーバーとして動作すれば良い。
LWA は Lambda Extension として Dockerfile に COPY --from 命令で組み込む。コンテナイメージの /opt/extensions/ ディレクトリに配置すると、Lambda Runtime が自動的に Extension として起動する。
主要な環境変数:
| 環境変数 | デフォルト | 説明 |
|---|---|---|
AWS_LWA_PORT | 8080 | App Server のリッスンポート |
AWS_LWA_READINESS_CHECK_PATH | / | ヘルスチェックエンドポイント |
AWS_LWA_READINESS_CHECK_PROTOCOL | http | ヘルスチェックプロトコル |
AWS_LWA_ASYNC_INIT | false | 非同期初期化 (JVM 系で有効) |
AWS_LWA_INVOKE_MODE | request_response | response_stream でストリーミング対応 |
- Lambda invoke → LWA Extension → localhost:PORT の HTTP App Server
- 既存の Express / FastAPI / Spring Boot を無改修で Lambda 化可能
- Lambda Function URL または API Gateway HTTP API と組み合わせ
6-2. Dockerfile への LWA 組み込み
LWA の組み込みは COPY --from 命令で ECR Public の公式イメージから取得するだけだ。Node.js (Express) と Python (FastAPI) の完全実装を示す。
Express (Node.js) + LWA の Dockerfile:
FROM public.ecr.aws/docker/library/node:20-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY src/ ./src/
FROM public.ecr.aws/docker/library/node:20-slim
WORKDIR /app
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 \
/lambda-adapter /opt/extensions/lambda-adapter
COPY --from=builder /app .
ENV PORT=8080
EXPOSE 8080
CMD ["node", "src/index.js"]
/opt/extensions/lambda-adapter に配置するだけで LWA が有効化される。CMD は既存の起動コマンドそのままで良い。PORT=8080 は App Server 側と LWA の AWS_LWA_PORT を揃えるための唯一の変更点だ。マルチステージビルドにより本番イメージには開発依存の node_modules が含まれない。
FastAPI (Python) + LWA の Dockerfile:
FROM public.ecr.aws/docker/library/python:3.12-slim
WORKDIR /app
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 \
/lambda-adapter /opt/extensions/lambda-adapter
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app/ .
ENV PORT=8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
uvicorn の起動コマンドも変更不要。--host 0.0.0.0 は LWA からのローカル接続を受け付けるために必要だ。Python は通常シングルステージビルドで十分だが、ビルド時依存 (gcc 等) が多い場合はマルチステージに切り出すと最終イメージを軽量化できる。
LWA のバージョンは public.ecr.aws/awsguru/aws-lambda-adapter の ECR Public ページで最新を確認すること。0.8.4 は 2024 年時点の安定版で、レスポンスストリーミングが本格サポートされたバージョンだ。
6-3. Terraform + Lambda Function URL 統合
Lambda Function URL を使うと API Gateway なしで直接 HTTP エンドポイントを公開できる。LWA との組み合わせで最もシンプルな構成だ。
Lambda Function URL の Terraform 実装:
resource "aws_lambda_function" "lwa_lambda" {
function_name = "express-app-lambda"
package_type = "Image"
image_uri = "${aws_ecr_repository.lwa_repo.repository_url}:latest"
role = aws_iam_role.lambda_exec.arn
architectures = ["arm64"]
timeout = 30
memory_size= 512
environment {
variables = {
PORT = "8080"
}
}
}
resource "aws_lambda_function_url" "lwa_url" {
function_name= aws_lambda_function.lwa_lambda.function_name
authorization_type = "NONE"
cors {
allow_origins = ["*"]
allow_methods = ["GET", "POST", "PUT", "DELETE"]
}
}
output "lambda_function_url" {
value = aws_lambda_function_url.lwa_url.function_url
}
authorization_type = "NONE" はパブリックアクセス。本番では AWS_IAM を設定してリクエスト署名を必須とすること。CORS の allow_origins は適切に絞り込むべきだ。
API Gateway HTTP API との統合:
より高度なルーティングや認証が必要な場合は API Gateway HTTP API (v2) を使う。
resource "aws_apigatewayv2_api" "lwa_api" {
name = "lwa-express-api"
protocol_type = "HTTP"
}
resource "aws_apigatewayv2_integration" "lwa_integration" {
api_id = aws_apigatewayv2_api.lwa_api.id
integration_type = "AWS_PROXY"
integration_uri = aws_lambda_function.lwa_lambda.invoke_arn
payload_format_version = "2.0"
}
resource "aws_apigatewayv2_route" "lwa_route" {
api_id = aws_apigatewayv2_api.lwa_api.id
route_key = "ANY /{proxy+}"
target = "integrations/${aws_apigatewayv2_integration.lwa_integration.id}"
}
resource "aws_apigatewayv2_stage" "lwa_stage" {
api_id= aws_apigatewayv2_api.lwa_api.id
name = "$default"
auto_deploy = true
}
resource "aws_lambda_permission" "lwa_apigw" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lwa_lambda.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.lwa_api.execution_arn}/*/*"
}
payload_format_version = "2.0" は HTTP API で推奨される形式。LWA は 1.0 / 2.0 両対応しているため、既存の REST API (v1) からの移行時も問題ない。route_key = "ANY /{proxy+}" により全パスを Lambda に転送し、Express のルーターがそのまま機能する。
6-4. AWS CLI での動作確認
デプロイ後の疎通確認は Function URL に直接 curl を送ることで即座に検証できる。
# Function URL を取得
FUNCTION_URL=$(aws lambda get-function-url-config \
--function-name express-app-lambda \
--query FunctionUrl --output text)
# GET リクエストのテスト
curl -s "$FUNCTION_URL/api/hello"
# POST リクエストのテスト
curl -s -X POST "$FUNCTION_URL/api/users" \
-H "Content-Type: application/json" \
-d '{"name": "Lambda User"}'
# レスポンスタイム計測 (cold start / warm 比較)
curl -s -w "\nTotal: %{time_total}s\n" "$FUNCTION_URL/api/hello"
CloudWatch Logs でも LWA の動作が確認できる。Extension の起動ログと App Server のアクセスログが混在して出力されるため、フィルタで切り分けると分かりやすい。
# 直近 5 分の LWA ログを確認
aws logs filter-log-events \
--log-group-name "/aws/lambda/express-app-lambda" \
--start-time $(date -d '5 minutes ago' +%s000) \
--filter-pattern "LWA"
6-5. LWA 活用パターンと注意点
- 既存 Express API の Lambda 移行: API Gateway + LWA でルーティングをそのまま利用。コード変更ゼロで移行可能
- FastAPI / Flask の Lambda 化: Python データ処理 API をサーバーレス化。EventBridge Scheduler と組み合わせたバッチ処理にも活用できる
- Spring Boot Lambda 化: JVM 系は SnapStart (Vol2 予告) との組み合わせが強力。ARM64 + Graviton3 で JVM コストも削減
- マイクロサービス移行の中間フォーム: ECS → Lambda の段階移行で LWA が「接着剤」として機能する
LWA と API Gateway の組み合わせについては API Gateway HTTP API + Lambda Authorizer 本番運用完全ガイド も参照してほしい。
- Extension 起動オーバーヘッド: LWA は Lambda Extension として動作するため、Extension 起動分だけ cold start が長くなる。Provisioned Concurrency での緩和を推奨
- WebSocket 非対応: LWA は HTTP/1.1 / HTTP/2 のみ対応。WebSocket 長期接続は Lambda タイムアウト (最大 15 分) の制約もあり、API Gateway WebSocket API + DynamoDB 接続管理の構成を選ぶこと
- ストリーミング応答: レスポンスストリーミングには
AWS_LWA_INVOKE_MODE=response_stream設定と Function URL が必要。API Gateway 経由ではストリーミング非対応 - ステートフルセッション不可: Lambda はリクエストごとに異なるコンテナで実行されるため、インメモリセッションは消える。ElastiCache / DynamoDB に外出しが必要
7. cold start 最適化 (5 つのレバー)

Container image Lambda は ZIP Lambda に比べて cold start が長くなりやすい。その主因は「イメージの pull とレイヤー展開」にある。しかし正しい最適化レバーを組み合わせることで、実運用上の問題を解消できる。本章では 5 つのレバーを体系的に解説する。
7-1. Lambda init phase の解剖
cold start を最小化するには、init phase が何をしているかを理解する必要がある。Lambda の cold start は大きく 3 フェーズに分かれる。
フェーズ 1: イメージ pull とレイヤー展開
Lambda は ECR からコンテナイメージをダウンロードし、ローカルキャッシュに展開する。イメージサイズが大きいほどこのフェーズが長くなる。ただし AWS は SOCI (Seek-Optimized Container Image) という技術でレイヤーを遅延展開しており、すべてのレイヤーが揃うまで待たずに起動を開始できる。
フェーズ 2: ランタイム起動
コンテナが起動し、Lambda Runtime Interface Client (RIC) がランタイムを初期化する。Python / Node.js は高速。JVM 系 (Java / Kotlin / Scala) はクラスロードに数百 ms〜数秒かかる場合がある。
フェーズ 3: 初期化コード実行
ハンドラー関数の外側 (グローバルスコープ) のコードが実行される。DB 接続プールの確立、設定ファイルの読み込み、ML モデルのロードなどがここに含まれる。初期化コードが重いほど cold start が延びる。
| フェーズ | 主な処理 | 最適化の余地 |
|---|---|---|
| イメージ pull | ECR → Lambda へのレイヤー転送 | イメージサイズ削減 / SOCI (自動適用) |
| ランタイム起動 | RIC + ランタイム初期化 | arm64 採用 / SnapStart (Vol2) |
| 初期化コード | グローバルスコープ処理 | 遅延初期化 / 並列初期化 |
7-2. レバー 1: image size 削減
イメージサイズと cold start 時間は正の相関がある。AWS が公開したベンチマーク (2023年) では、1GB のイメージは 500MB のイメージに比べて cold start が約 400〜600ms 長くなる傾向がある (リージョン・ハードウェアにより変動)。
削減目標の目安
| イメージサイズ | 想定 cold start (ウォームなし) | 推奨アクション |
|---|---|---|
| < 100MB | 300〜700ms | 問題なし |
| 100MB〜500MB | 600ms〜1.5s | multi-stage で最適化を検討 |
| 500MB〜2GB | 1.5s〜4s | provisioned concurrency と組み合わせ |
| > 2GB | 4s 以上 | 必ずプロビジョニングか SnapStart (Vol2) を検討 |
削減テクニック
# 現在のイメージサイズ確認
docker images --format "{{.Repository}}:{{.Tag}}\t{{.Size}}"
# dive でレイヤー別サイズ分析
docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
wagoodman/dive:latest <image>:<tag>
- multi-stage ビルド (§4 参照) でビルド成果物のみをランタイムにコピー
.dockerignoreでtests//docs//*.md/.git/を除外- pip install
--no-cache-dir+--only-binary :all:で不要ファイルを排除 - AWS Lambda Powertools を Lambda Layer に分離 (Vol3 予告)
7-3. レバー 2: provisioned concurrency
provisioned concurrency はインスタンスを常時ウォームな状態で維持することで cold start を事実上ゼロにする。SLA が厳格なエンドポイントや夜間バッチ起動後の burst 対応に有効。
Terraform 完全実装
# Lambda エイリアス (バージョン管理)
resource "aws_lambda_alias" "production" {
name = "production"
function_name = aws_lambda_function.container_lambda.function_name
function_version = aws_lambda_function.container_lambda.version
}
# provisioned concurrency 設定
resource "aws_lambda_provisioned_concurrency_config" "production" {
function_name= aws_lambda_alias.production.function_name
qualifier = aws_lambda_alias.production.name
provisioned_concurrent_executions = 5
}
# Application Auto Scaling でスケジュール管理
resource "aws_appautoscaling_target" "lambda_target" {
max_capacity = 20
min_capacity = 2
resource_id = "function:${aws_lambda_function.container_lambda.function_name}:production"
scalable_dimension = "lambda:function:ProvisionedConcurrency"
service_namespace = "lambda"
}
resource "aws_appautoscaling_scheduled_action" "scale_up_morning" {
name= "scale-up-morning"
service_namespace = aws_appautoscaling_target.lambda_target.service_namespace
resource_id = aws_appautoscaling_target.lambda_target.resource_id
scalable_dimension = aws_appautoscaling_target.lambda_target.scalable_dimension
schedule = "cron(0 8 * * ? *)"# JST 17:00 = UTC 08:00
scalable_target_action {
min_capacity = 5
max_capacity = 20
}
}
AWS CLI で設定確認:
# provisioned concurrency 設定確認
aws lambda get-provisioned-concurrency-config \
--function-name my-container-lambda \
--qualifier production
# 設定後の cold start 確認 (メトリクス)
aws cloudwatch get-metric-statistics \
--namespace AWS/Lambda \
--metric-name InitDuration \
--dimensions Name=FunctionName,Value=my-container-lambda \
--start-time $(date -u -d '1 hour ago' '+%Y-%m-%dT%H:%M:%S') \
--end-time $(date -u '+%Y-%m-%dT%H:%M:%S') \
--period 300 \
--statistics Average
コスト試算: provisioned concurrency は設定数 × 稼働時間で課金。5 並行 × 512MB × 720h/月 ≒ $36/月 (us-east-1 目安)。必要な時間帯のみ Application Auto Scaling で絞ることでコスト最適化できる。
7-4. レバー 3: init phase の短縮
グローバルスコープの重い処理を遅延初期化することで、cold start のフェーズ 3 を短縮する。
遅延初期化パターン (Python)
import boto3
from functools import lru_cache
# ❌ 悪い例: モジュール読み込み時に重い処理
# db_client = boto3.client('dynamodb') # cold startのたびに接続確立
# ✅ 良い例: 初回呼び出し時に初期化 (以降はキャッシュ)
_db_client = None
def get_db_client():
global _db_client
if _db_client is None:
_db_client = boto3.client('dynamodb')
return _db_client
def lambda_handler(event, context):
client = get_db_client() # 初回のみ初期化、2回目以降はキャッシュ
# ...
並列初期化パターン (Node.js)
// 複数の非同期初期化を並列化
let dbClient, s3Client, secretValue;
const initialize = async () => {
[dbClient, s3Client, secretValue] = await Promise.all([
createDynamoDBClient(),
createS3Client(),
getSecret('/app/config'),
]);
};
// グローバルスコープで並列初期化を起動
const initPromise = initialize();
exports.handler = async (event) => {
await initPromise; // 初期化完了を待つ (2回目以降は即解決)
// ...
};
ML モデルのウォームアップ: 大規模モデル (1GB 以上) はグローバルスコープでロードすると cold start が長くなる。モデルを S3 から pull してキャッシュする場合は /tmp (最大 10GB) を活用する。
7-5. レバー 4: arm64 (Graviton) 採用
Lambda の arm64 (Graviton2) は x86_64 に比べて以下の利点がある。
| 指標 | arm64 (Graviton2) | x86_64 |
|---|---|---|
| 実行コスト | 約 20% 削減 | 基準 |
| cold start | 同等〜やや改善 | 基準 |
| スループット | 同等〜改善 | 基準 |
| 対応ランタイム | Python / Node.js / Java / Go / Ruby | すべて |
Terraform での arm64 設定:
resource "aws_lambda_function" "container_lambda_arm64" {
function_name = "my-container-lambda-arm64"
package_type = "Image"
image_uri = "${aws_ecr_repository.lambda_repo.repository_url}:arm64"
role = aws_iam_role.lambda_exec.arn
architectures = ["arm64"]# ← ここを変更するだけ
timeout = 30
memory_size= 512
}
注意点: arm64 イメージは --platform linux/arm64 でビルドしたものを使う (§4 参照)。multi-arch manifest がある場合は Lambda が自動的に適切なアーキテクチャのレイヤーを選択する。
AWS CLI での切り替え確認:
# 現在のアーキテクチャ確認
aws lambda get-function-configuration \
--function-name my-container-lambda \
--query 'Architectures'
# arm64 に切り替え (ZIP Lambda の場合; Container image は Terraform で管理)
aws lambda update-function-configuration \
--function-name my-container-lambda \
--architectures arm64
7-6. レバー 5: SnapStart (Vol2 予告)
SnapStart は Lambda 関数の初期化済みスナップショットを事前に作成し、cold start を事実上ゼロ (50ms 以下) にする AWS の機能。
重要: SnapStart は ZIP Lambda のみ対応。Container image Lambda と SnapStart を組み合わせることはできない。Container image の cold start を最小化するには本章のレバー 1〜4 を組み合わせること。
- レバー 1: image size 削減 — multi-stage ビルド・.dockerignore・–no-cache-dir で 500MB 以下を目標に
- レバー 2: provisioned concurrency — 常時ウォームキープ。SLA 厳格なエンドポイントに必須
- レバー 3: init phase 短縮 — 遅延初期化・並列初期化でグローバルスコープを軽量化
- レバー 4: arm64 採用 — 20% コスト削減 + cold start 同等以上。新規作成は arm64 推奨
- レバー 5: SnapStart — ZIP Lambda のみ対応。Container image との併用不可。詳細は Vol2 で深掘り
SnapStart の設計詳細と Container image との棲み分けについては Lambda 応用シリーズ Vol2: SnapStart 完全活用編 で詳しく解説する予定。
推奨組み合わせ (ワークロード別)
| ワークロード | 推奨レバー |
|---|---|
| 軽量 API (< 200MB) | arm64 のみで十分 |
| 中規模依存 (200MB〜1GB) | image size 削減 + arm64 |
| 大規模 ML 推論 (> 1GB) | provisioned concurrency + image size 削減 |
| レイテンシ SLA 厳格 | provisioned concurrency (必須) |
| JVM / Python 初期化重い | init phase 短縮 + provisioned |
8. まとめ + Vol2 予告 + 落とし穴 10 選
本記事では Container image Lambda を本番運用するために必要な知識を §1〜§7 で体系的に解説した。最後に要点をチートシートにまとめ、実運用で踏みやすい落とし穴 10 選を提示する。
8-1. 本記事のチートシート
| テーマ | 要点 | 参照章 |
|---|---|---|
| ZIP vs Container 選定 | 依存 200MB 超 / HTTP サーバー流用 / multi-arch 必要 → Container image | §3 |
| Dockerfile base image | 新規は public.ecr.aws/lambda/* 推奨。既存 HTTP サーバーは任意 OCI + LWA | §4 |
| multi-stage ビルド | Builder → Runtime で最終イメージを最小化。.dockerignore 必須 | §4 |
| multi-arch | docker buildx --platform linux/amd64,linux/arm64 + TARGETPLATFORM | §4 |
| ECR push pipeline | CodeBuild (VPC統合◎) vs GHA OIDC (GitHub 中心◎) を要件で選択 | §5 |
| Lambda Web Adapter | COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter + ENV PORT=8080 | §6 |
| cold start 最適化 | レバー順位: ① arm64 ② image size 削減 ③ init 短縮 ④ provisioned | §7 |
| provisioned concurrency | aws_lambda_provisioned_concurrency_config + Auto Scaling でコスト管理 | §7 |
よく使う AWS CLI コマンド早見表
# ECR ログイン
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin \
<ACCOUNT>.dkr.ecr.us-east-1.amazonaws.com
# multi-arch ビルド & push
docker buildx build --platform linux/amd64,linux/arm64 \
-t <ACCOUNT>.dkr.ecr.us-east-1.amazonaws.com/my-lambda:latest --push .
# Lambda デプロイ & 完了待ち
aws lambda update-function-code \
--function-name my-container-lambda \
--image-uri <ACCOUNT>.dkr.ecr.us-east-1.amazonaws.com/my-lambda:latest
aws lambda wait function-updated --function-name my-container-lambda
# cold start メトリクス確認
aws cloudwatch get-metric-statistics \
--namespace AWS/Lambda --metric-name InitDuration \
--dimensions Name=FunctionName,Value=my-container-lambda \
--start-time $(date -u -d '1 hour ago' '+%Y-%m-%dT%H:%M:%S') \
--end-time $(date -u '+%Y-%m-%dT%H:%M:%S') \
--period 3600 --statistics Average
8-2. 本番投入の落とし穴 10 選
- イメージサイズ 1GB 超でも provisioned concurrency なし
cold start が 3〜5 秒になり SLA 違反。イメージサイズ × 使用パターンで必要な provisioned 数を試算してから本番投入すること。 - multi-arch manifest を作らず single-arch (x86_64) のみ push
arm64 環境で実行すると「exec format error」が発生。docker buildx --platform linux/amd64,linux/arm64で manifest list を作成すること。 - ECR lifecycle policy 未設定でイメージが無限増殖
デプロイのたびに新タグが増え、ECR ストレージ費が膨らむ。imageCountMoreThan: 10程度の lifecycle policy を必ず設定すること。 - LWA のヘルスチェックパスを設定せず起動失敗
LWA はデフォルトで/への HTTP GET でアプリの起動を確認する。アプリが/を実装していない場合はAWS_LWA_READINESS_CHECK_PATHに正しいパスを設定すること。 - Lambda Function URL の認証を NONE のまま本番公開
authorization_type = "NONE"はエンドポイントが全公開になる。本番ではAWS_IAM認証 + Lambda URL の署名 v4 リクエスト、または API Gateway 側で制御すること。 - IAM ロールに
ecr:*などワイルドカード権限を付与
最小権限原則に反する。Lambda にはecr:GetDownloadUrlForLayer/ecr:BatchGetImage/ecr:GetAuthorizationTokenの 3 つのみ付与すれば動作する。 - ECR image scanning を OFF にしたまま運用
脆弱性スキャンが効かない状態でイメージが本番稼働し続ける。scan_on_push = trueを設定し、Critical / High の CVE が出た場合はアラートを CloudWatch + SNS で設定すること。 - update-function-code 後に
lambda:wait function-updatedを省略
デプロイが完了する前に次の invoke が走り、古いイメージが呼ばれることがある。CI/CD パイプラインでは必ずaws lambda wait function-updatedを実行すること。 - コンテナ内に AWS 認証情報をハードコード
Dockerfile や app コード内にAWS_ACCESS_KEY_IDを直書きするのは絶対禁止。Lambda 実行ロールのクレデンシャルが自動的に環境変数として注入されるため、SDK デフォルト認証チェーンを使うこと。 - ロールバック手順を整備せずデプロイ
Container image Lambda はバージョン管理 + Lambda エイリアスを使うことで即時ロールバックが可能。デプロイ前にaws_lambda_alias+ 旧バージョン指定をインフラコードに組み込んでおくこと。
8-3. Vol2 予告: SnapStart 完全活用編
SnapStart は Lambda 関数の init phase 完了直後のメモリスナップショットを S3 に保存し、以降の cold start 時にスナップショットから復元することで cold start を 50ms 以下に抑える機能だ。
ただし現時点 (2026年) では ZIP パッケージのみ対応であり、Container image Lambda には適用できない。Vol2 では以下のテーマを深掘りする予定だ。
- SnapStart 対応ランタイムと対応外ランタイムの整理
- Container image Lambda vs ZIP Lambda + SnapStart の cold start 実測比較
- SnapStart 有効化手順 (Terraform + コンソール)
- SnapStart と provisioned concurrency の使い分け判断フロー
- UniqueID / Network connections のスナップショット安全性
- Vol2: SnapStart 完全活用編 — JVM / Python / Node の cold start を ms 単位に圧縮する SnapStart の本番設計と Container image との併用制約を完全解説
- Vol3: Powertools + Layers 統合運用編 — observability / parameter / idempotency の標準化と Layers 配布戦略 (準備中)
8-4. 本番投入前 デプロイチェックリスト
Container image Lambda を本番投入する前に以下を確認しよう。
インフラ設定
- [ ] ECR repository 作成 + lifecycle policy 設定 (imageCountMoreThan: 10 以下)
- [ ] ECR image scanning (
scan_on_push = true) 有効化 - [ ] Lambda 実行ロールに ECR 最小権限 (GetDownloadUrlForLayer / BatchGetImage / GetAuthorizationToken) を付与
- [ ] Lambda function 設定:
package_type = "Image"/architectures = ["arm64"]/ タイムアウト適切か確認 - [ ] CloudWatch Logs グループに適切な retention 設定
Dockerfile / イメージ
- [ ] multi-stage ビルドでイメージサイズを最小化 (500MB 以下を目標)
- [ ]
.dockerignoreで tests / docs / .git を除外 - [ ] multi-arch manifest (
linux/amd64,linux/arm64) を作成済み - [ ] LWA 使用時:
ENV PORT=8080とAWS_LWA_READINESS_CHECK_PATHを設定
パイプライン
- [ ] CI/CD パイプライン (CodeBuild または GHA OIDC) でビルド → push →
update-function-code→wait function-updatedの順序を確認 - [ ] 旧バージョンへのロールバック手順を整備 (
aws_lambda_aliasでバージョン管理)
cold start 対策
- [ ] cold start 許容 SLA を定義 (300ms / 1s / 5s 等)
- [ ] SLA 厳格な場合:
aws_lambda_provisioned_concurrency_config設定 - [ ] arm64 採用で 20% コスト削減を確認
セキュリティ
- [ ] AWS 認証情報のハードコードがないことを確認 (truffleHog / git-secrets でスキャン)
- [ ] Function URL を使用する場合は
authorization_type = "AWS_IAM"または API Gateway 認証を設定 - [ ] ECR リポジトリポリシーでプルアクセスを最小化
8-5. 関連記事
本記事で解説した Lambda + API Gateway の統合パターンをさらに深掘りしたい場合は以下の関連記事も参照してほしい。
- API Gateway HTTP API + Lambda Authorizer 本番運用完全ガイド — Lambda Authorizer による認証設計・JWT / Cognito 統合・Terraform 完全実装
- EventBridge Scheduler 本番運用完全ガイド — Container image Lambda を EventBridge Scheduler からキックするスケジュール実行パターン