NO IMAGE

Container image Lambda 本番運用 multi-arch LWA cold start

NO IMAGE
目次

1. この記事について

fig01: Container image Lambda 全体アーキテクチャ

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 を構築できる」ことをゴールとしている。

【シリーズ】Lambda 応用シリーズ (全3巻)

  • 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 軸で整理する。

本記事の差別化6軸

  1. 10GB イメージ活用 + multi-arch (arm64/x86_64) 対応を1本で網羅
    国内記事の多くは ZIP からの移行入門にとどまる。本記事は 10GB イメージを活かした大規模 ML 推論・FFmpeg・OCR 等の重量ワークロードと、docker buildx + TARGETPLATFORM を用いた multi-arch manifest による arm64 / x86_64 同時配布を §4-§5 で完全実装する。
  2. Lambda Web Adapter (LWA) による既存 HTTP サーバーのサーバーレス化を詳解
    Express / FastAPI / Spring Boot 等の既存 HTTP サーバー資産をほぼ無改修で Lambda 化できる LWA の内部経路 (HTTP Request → LWA Extension → 内部 App Server) を §6 で徹底解剖する。LWA を含む統合解説は国内記事でも希少である。
  3. ZIP Lambda との選択軸・移行判断フローを提供
    サイズ上限 / cold start / デプロイ速度 / ユースケース / コストの 5 軸比較マトリクスと移行判断ツリーを §3 に掲載する。「移行すべきか・ZIP のまま継続すべきか・用途別に併用すべきか」を読者が自己判断できる構成とした。
  4. cold start 最適化のロードマップ (Vol1 → Vol2 SnapStart)
    provisioned concurrency / image size 削減 / init phase 短縮 / arm64 採用 / SnapStart (Vol2 予告) の 5 レバーを §7 で俯瞰し、Vol2 (SnapStart 完全活用編) への橋渡しを行う。cold start を実用域に収める段階的な最適化ロードマップを提示する。
  5. Terraform + AWS CLI + コンソール 3 点セット完走
    §4〜§7 の全章を Terraform HCL 完全実装・AWS CLI コマンド・コンソール操作の 3 形式で提供する。コマンドはそのままコピー&ペーストで動くレベルの精度で掲載し、「本番投入できる」を担保する。
  6. シリーズナビ 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・ゴール状態の定義
§3Container image Lambda 全体像 + ZIP との比較5 軸比較 + 移行判断フロー + 全体アーキテクチャ
§4Dockerfile 完全解説multi-stage / multi-arch / base image 選定
§5ECR push pipeline + Lambda 更新CodeBuild + GHA OIDC 両構成 Terraform
§6Lambda Web AdapterHTTP server を Lambda 化する黄金パターン
§7cold start 最適化5 つの最適化レバー + Vol2 SnapStart 予告
§8まとめ + Vol2 予告 + 落とし穴 10 選チートシート

1-5. 想定環境

本記事のサンプルコードは以下の環境で動作検証した。ローカル開発環境は macOS (Apple Silicon) で検証しているが、Windows / Linux でも同一手順で再現できる。

ツール / サービスバージョン / 仕様
Terraform1.9.x (aws provider 5.x)
AWS CLIv2 (2.15.x 以降推奨)
Docker / docker buildx最新安定版 (BuildKit 有効)
Lambda ランタイムPython 3.12 / Node.js 20 / Java 21
Amazon ECRus-east-1 (サンプルリージョン)
Lambda Web Adapterv0.8.x (Lambda Layer 形式)
Git2.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. 前提・環境・準備

fig02: Container image vs ZIP Lambda 比較マトリクス

2-1. 前提環境

本記事を進めるにあたり、以下の環境・権限が整っていることを事前に確認してほしい。

AWS アカウント・IAM 権限

以下の IAM アクションが必要である。最小権限原則に従い、開発者ロールまたは CI/CD ロールに付与する。

IAM アクション用途
ecr:CreateRepository ecr:GetAuthorizationToken ecr:BatchCheckLayerAvailability ecr:PutImage ecr:InitiateLayerUpload ecr:UploadLayerPart ecr:CompleteLayerUploadECR リポジトリ作成・イメージ push
lambda:CreateFunction lambda:UpdateFunctionCode lambda:UpdateFunctionConfiguration lambda:GetFunctionConfigurationLambda 関数のデプロイ・設定変更
codebuild:CreateProject codebuild:StartBuildECR push pipeline (CodeBuild) 操作
s3:PutObject s3:GetObjectCodeBuild アーティファクト保管
iam:PassRoleLambda 実行ロール・CodeBuild ロールの付与

ローカル開発環境

ツール最低バージョンインストール確認コマンド
Docker / docker buildx最新安定版 (BuildKit 有効)docker buildx version
AWS CLIv2 (2.15.x 以降)aws --version
Terraform1.9.xterraform version
Git2.x 以降git --version

想定リージョンは us-east-1 である。別リージョンを使用する場合、§3 以降の Terraform コードの aws_region 変数を変更すること。

2-2. 使用技術スタック

本記事で使用するサービス・ライブラリを以下にまとめる。

カテゴリサービス / ライブラリ概要
コンピュートLambda (package_type=Image)Container image 形式の Lambda 実行環境
レジストリAmazon ECROCI コンテナイメージの格納・管理
ビルドDocker BuildKit / buildxmulti-arch イメージのビルド・キャッシュ最適化
CI/CD (クラウド)AWS CodeBuildECR への自動 push pipeline (AWS ネイティブ)
CI/CD (GitHub)GitHub Actions + OIDCECR への自動 push pipeline (OIDC 連携)
IaCTerraform aws provider 5.xインフラ全体の宣言的管理
HTTP アダプタLambda Web Adapter (LWA) v0.8.x既存 HTTP サーバーの Lambda 化 Extension
モニタリングAmazon CloudWatch LogsLambda 実行ログの収集・保管
スケーリングProvisioned Concurrencycold 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 Lambdapackage_type = "Image" で設定される Lambda デプロイ形式。OCI 準拠コンテナイメージを ECR に push し Lambda 関数として実行する。
OCI (Open Container Initiative)コンテナイメージ形式の業界標準規格。Docker image は OCI 準拠であり ECR で保管・配布できる。
multi-arch1 つのイメージタグで arm64 (Graviton) と x86_64 の両 CPU アーキテクチャに対応する multi-platform manifest list を使う構成。
TARGETPLATFORMdocker buildx build --platform で渡されるビルドターゲット情報 (linux/amd64 / linux/arm64)。Dockerfile 内で ARG TARGETPLATFORM として参照できる。
BuildKitDocker の次世代ビルドエンジン。並列ビルド・キャッシュマウント・multi-arch ビルドを高速化する。DOCKER_BUILDKIT=1 または docker buildx で有効になる。
LWA (Lambda Web Adapter)AWS が OSS で提供する Lambda Extension。HTTP リクエストを Lambda イベントに変換し、内部で起動した HTTP サーバーへプロキシする。既存の Express / FastAPI / Spring Boot 等をほぼ無改修で Lambda 化できる。
cold startLambda がコールドな状態 (インスタンス非起動) で初回リクエストを受けた際に発生する初期化遅延。Container image は ZIP より init 時間が長くなりやすい。
init phasecold 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 + transformers2〜4 GB
FFmpeg 動画処理ffmpeg binary + ffprobe100〜200 MB
OCR (Tesseract)tesseract + language packs500 MB〜2 GB
Java Spring BootJDK + Spring dependencies200〜600 MB
Node.js + 大規模 npmnode_modules + native addon300〜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" }
 }
  ]
}
QG-1: Container image Lambda 全体アーキテクチャ

  • 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 imageZIP 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 MB1〜2 秒通常許容範囲
100 MB〜1 GB2〜8 秒arm64 + 軽量 base image
1 GB〜4 GB8〜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 以上のイメージを維持する場合はコストが積み上がるため注意が必要である。

QG-2: Container image vs ZIP Lambda 5 軸比較

  • サイズ: 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 が実質的な唯一の選択肢となるケースが多い。

判断軸推奨形式決め手
サイズ > 200MBContainer imageZIP 制限回避
HTTP サーバーの Lambda 化Container image + LWADockerfile 流用
multi-arch 管理Container imageECR manifest list
Provisioned Concurrency ありContainer imagecold start 解消
軽量関数 + コスト最小ZIP LambdaECR 費用不要

3-4. 採用してはいけないケース

Container image Lambda が逆効果になるパターン

  • 極小関数 (依存なし・数 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 選定)

fig03: Dockerfile multi-stage / multi-arch ビルド構造

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 MBAWS 最適化・Lambda Runtime API 内蔵新規 Python Lambda 開発
public.ecr.aws/lambda/nodejs:20~160 MBNode.js Lambda 最適化・NPM 付属Node.js Lambda
public.ecr.aws/lambda/java:21~300 MBJava 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 選定フロー:

  1. 新規 Lambda 開発かつ AWS 最適化を優先する場合 → public.ecr.aws/lambda/* を使う
  2. 既存 Docker アプリ (Express / FastAPI 等の HTTP サーバー) を流用する場合 → 任意 OCI + Lambda Web Adapter
  3. セキュリティ要件が厳しくシェルアクセスを排除したい場合 → distroless + custom RIC
  4. イメージサイズを極限まで削減したい上級者向け → 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/amd64linux/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 へ切り替えて性能テストを実施し、メモリサイズのチューニングと組み合わせるのが定石である。

QG-3: Dockerfile multi-stage / multi-arch ビルドフロー

  • 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:alpinepython: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 更新

fig04: ECR push pipeline 設計 (CodeBuild + GHA OIDC 両パターン)

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 選定軸

観点CodeBuildGHA 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 化)

fig05: Lambda Web Adapter (LWA) アーキテクチャ

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 が発生すると、以下の経路でリクエストが処理される。

  1. API Gateway / Function URL / ALB が Lambda を invoke
  2. LWA Extension が Lambda イベント (JSON ペイロード) を受信
  3. LWA がイベントを HTTP Request に変換
  4. localhost:PORT (デフォルト 8080) で動作する内部 App Server に転送
  5. App Server が HTTP Response を返却
  6. LWA が HTTP Response → Lambda レスポンス形式 (JSON) に変換して返す

この変換レイヤーにより、既存コードへの変更は不要だ。必要なのは PORT 環境変数の設定のみ。Lambda Runtime API との通信は LWA が全て処理するため、アプリ側は通常の HTTP サーバーとして動作すれば良い。

LWA は Lambda Extension として Dockerfile に COPY --from 命令で組み込む。コンテナイメージの /opt/extensions/ ディレクトリに配置すると、Lambda Runtime が自動的に Extension として起動する。

主要な環境変数:

環境変数デフォルト説明
AWS_LWA_PORT8080App Server のリッスンポート
AWS_LWA_READINESS_CHECK_PATH/ヘルスチェックエンドポイント
AWS_LWA_READINESS_CHECK_PROTOCOLhttpヘルスチェックプロトコル
AWS_LWA_ASYNC_INITfalse非同期初期化 (JVM 系で有効)
AWS_LWA_INVOKE_MODErequest_responseresponse_stream でストリーミング対応
QG-4: Lambda Web Adapter アーキテクチャ

  • 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 活用パターンと注意点

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 本番運用完全ガイド も参照してほしい。

LWA 採用時の注意点

  • 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 つのレバー)

fig06: cold start 最適化戦略マップ

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 が延びる。

フェーズ主な処理最適化の余地
イメージ pullECR → Lambda へのレイヤー転送イメージサイズ削減 / SOCI (自動適用)
ランタイム起動RIC + ランタイム初期化arm64 採用 / SnapStart (Vol2)
初期化コードグローバルスコープ処理遅延初期化 / 並列初期化

7-2. レバー 1: image size 削減

イメージサイズと cold start 時間は正の相関がある。AWS が公開したベンチマーク (2023年) では、1GB のイメージは 500MB のイメージに比べて cold start が約 400〜600ms 長くなる傾向がある (リージョン・ハードウェアにより変動)。

削減目標の目安

イメージサイズ想定 cold start (ウォームなし)推奨アクション
< 100MB300〜700ms問題なし
100MB〜500MB600ms〜1.5smulti-stage で最適化を検討
500MB〜2GB1.5s〜4sprovisioned concurrency と組み合わせ
> 2GB4s 以上必ずプロビジョニングか 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 参照) でビルド成果物のみをランタイムにコピー
  • .dockerignoretests/ / 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 を組み合わせること。

QG-5: cold start 最適化戦略マップ

  • レバー 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-archdocker buildx --platform linux/amd64,linux/arm64 + TARGETPLATFORM§4
ECR push pipelineCodeBuild (VPC統合◎) vs GHA OIDC (GitHub 中心◎) を要件で選択§5
Lambda Web AdapterCOPY --from=public.ecr.aws/awsguru/aws-lambda-adapter + ENV PORT=8080§6
cold start 最適化レバー順位: ① arm64 ② image size 削減 ③ init 短縮 ④ provisioned§7
provisioned concurrencyaws_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 選

Container image Lambda 本番投入 — 落とし穴 10 選

  1. イメージサイズ 1GB 超でも provisioned concurrency なし
    cold start が 3〜5 秒になり SLA 違反。イメージサイズ × 使用パターンで必要な provisioned 数を試算してから本番投入すること。
  2. multi-arch manifest を作らず single-arch (x86_64) のみ push
    arm64 環境で実行すると「exec format error」が発生。docker buildx --platform linux/amd64,linux/arm64 で manifest list を作成すること。
  3. ECR lifecycle policy 未設定でイメージが無限増殖
    デプロイのたびに新タグが増え、ECR ストレージ費が膨らむ。imageCountMoreThan: 10 程度の lifecycle policy を必ず設定すること。
  4. LWA のヘルスチェックパスを設定せず起動失敗
    LWA はデフォルトで / への HTTP GET でアプリの起動を確認する。アプリが / を実装していない場合は AWS_LWA_READINESS_CHECK_PATH に正しいパスを設定すること。
  5. Lambda Function URL の認証を NONE のまま本番公開
    authorization_type = "NONE" はエンドポイントが全公開になる。本番では AWS_IAM 認証 + Lambda URL の署名 v4 リクエスト、または API Gateway 側で制御すること。
  6. IAM ロールに ecr:* などワイルドカード権限を付与
    最小権限原則に反する。Lambda には ecr:GetDownloadUrlForLayer / ecr:BatchGetImage / ecr:GetAuthorizationToken の 3 つのみ付与すれば動作する。
  7. ECR image scanning を OFF にしたまま運用
    脆弱性スキャンが効かない状態でイメージが本番稼働し続ける。scan_on_push = true を設定し、Critical / High の CVE が出た場合はアラートを CloudWatch + SNS で設定すること。
  8. update-function-code 後に lambda:wait function-updated を省略
    デプロイが完了する前に次の invoke が走り、古いイメージが呼ばれることがある。CI/CD パイプラインでは必ず aws lambda wait function-updated を実行すること。
  9. コンテナ内に AWS 認証情報をハードコード
    Dockerfile や app コード内に AWS_ACCESS_KEY_ID を直書きするのは絶対禁止。Lambda 実行ロールのクレデンシャルが自動的に環境変数として注入されるため、SDK デフォルト認証チェーンを使うこと。
  10. ロールバック手順を整備せずデプロイ
    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 のスナップショット安全性
【シリーズ】Lambda 応用シリーズ — 次巻予告

  • Vol2: SnapStart 完全活用編 — JVM / Python / Node の cold start を ms 単位に圧縮する SnapStart の本番設計と Container image との併用制約を完全解説
  • Vol3: Powertools + Layers 統合運用編 — observability / parameter / idempotency の標準化と Layers 配布戦略 (準備中)

Vol2 SnapStart 完全活用編を読む

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=8080AWS_LWA_READINESS_CHECK_PATH を設定

パイプライン

  • [ ] CI/CD パイプライン (CodeBuild または GHA OIDC) でビルド → push → update-function-codewait 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 の統合パターンをさらに深掘りしたい場合は以下の関連記事も参照してほしい。