
目次
はじめに
Docker イメージとしてパッケージ化したアプリケーションを AWS Lambda にデプロイした際の手順をまとめました。
なお、関連するリソースはすべて Terraform によって管理しています。
イメージを用意する
- まずはDockerDesktopを起動しましょう。
持ってない方は公式よりインストールしてください。
- ベースイメージの取得
docker runコマンドでAWS が提供している Lambda 用ベースイメージを取得します。
> docker pull public.ecr.aws/lambda/python:3.12
3.13: Pulling from lambda/python
b71754c34aa3: Pull complete
d2379533db7f: Pull complete
26c6d8a1e1c2: Pull complete
94f2ecca3b37: Pull complete
f9e394d707b7: Pull complete
15b946295de2: Pull complete
Digest: sha256:e78bfe2edd6206a58448bbeb08164c7c420fc974b38e21cefbcd8ed2e7f2d49c
Status: Downloaded newer image for public.ecr.aws/lambda/python:3.13
public.ecr.aws/lambda/python:3.13
これでイメージが取得できました。
確認すると、
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
public.ecr.aws/lambda/python 3.13 f1006010e0ac 2 days ago 528MB
イメージの中身を作成する
Lambdaを動かすにはハンドラが必要なので、最小限のサンプルを作成します。
sampleフォルダを作成し、配下にapp.pyとDockerfileを作成します。
app.pyに下記を記述します。
def handler(event, context):
return {"statusCode": 200, "body": "Hello from Lambda container!"}
ステータスコード200と「Hello from Lambda container!」を返すシンプルなコードです。
Dockerfileも作成します。
FROM public.ecr.aws/lambda/python:3.12
COPY app.py ${LAMBDA_TASK_ROOT}
CMD ["app.handler"]
Dockerfileの内容は下記の通りです。
- 先ほどプルしたベースイメージを使用する。
app.pyをコンテナ内の Lambda タスクルートディレクトリ(/var/task)にコピーする。- Lambda が呼び出すハンドラー関数を
appモジュールのhandler関数で指定する。
ここまで出来たら、作成したプロジェクトをDockerイメージとしてビルドします。
sampleディレクトリに移動してから下記のコマンドを実行します。
docker build -t sample-image:latest-01 -f Dockerfile ./
Terraformを新規作成
必要なAWSリソースを作成するため、Terraformのプロジェクトを用意します。
Terraformについてはこちらをご覧ください。
Terraformのインストール方法についてはこちらをご覧ください。
sample-infrastructerフォルダを作成し、配下にmian.tf、variables.tf、terraform.tfvarsを作成します。
各フォルダに下記を記述します。
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
profile = var.profile
region = var.region
default_tags {
tags = {
Terraform = true
SystemName = "test"
}
}
}
※今回はstateファイルはローカルに保存する設定となっています。
# variables.tf
variable "profile" {
type = string
default = ""
}
variable "region" {
type = string
default = ""
}
# terraform.tfvars
profile = "xxxxxxxx"
region = "xxxxxxx"
profileは構築先のAWSアカウントのプロファイル名を記載してください。
>terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.100.0...
- Installed hashicorp/aws v5.100.0 (signed by HashiCorp)
Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
これでTerraformの準備ができました。
AWSリソースを作成する
- 必要なAWSリソースの設定ファイルを作成します。
sample-infrastructerフォルダ配下にecr.tf、lambda.tf、iam.tfを作成します。
各ファイルに下記を記述します。
# ------------------------------------------------------ #
# ECR
# ------------------------------------------------------ #
resource "aws_ecr_repository" "example" {
name = "example-repo"
image_tag_mutability = "IMMUTABLE"
force_delete = true
}
# ライフサイクルポリシー
resource "aws_ecr_lifecycle_policy" "example" {
repository = aws_ecr_repository.example.name
policy = jsonencode(
{
rules = [
{
rulePriority = 1,
description = "Keep last 10 images",
selection = {
tagStatus = "any",
countType = "imageCountMoreThan",
countNumber = 10
},
action = {
type = "expire"
}
}
]
}
)
}
####################################################
# Data sources for ECR images
####################################################
data "aws_ecr_image" "example_latest" {
repository_name = aws_ecr_repository.example.name
most_recent = true
}
# ------------------------------------------------------ #
# Lambda - using ECR image
# ------------------------------------------------------ #
resource "aws_lambda_function" "lambda" {
function_name = "lambda-test"
architectures = ["x86_64"]
package_type = "Image"
image_uri = data.aws_ecr_image.example_latest.image_uri
role = aws_iam_role.lambda_role.arn
publish = true
memory_size = 512
timeout = 30
}
# ------------------------------------------------------ #
# Lambda IAM Role and Policies
# ------------------------------------------------------ #
# Lambda Assume Role ポリシードキュメント
data "aws_iam_policy_document" "lambda_assume_role_policy" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "lambda_role" {
name = "example_lambda_iam_role"
assume_role_policy = data.aws_iam_policy_document.lambda_assume_role_policy.json
}
# AWSマネージドポリシーをアタッチ (CloudWatch Logsへの書き込み権限)
resource "aws_iam_role_policy_attachment" "lambda_basic_execution" {
role = aws_iam_role.lambda_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
- リソースを作成する
cliでAWSにログインします。
<profile-name>には構築先のAWSアカウントのプロファイル名を入力してください。
aws sso login --prifile <profile_name>
作成されるリソース一覧を確認します。
terraform plan -var-file="terraform.tfvars"
今回、DockerファイルはTerraformとは別プロジェクトにおいてますので、先にECRを用意して手動でイメージをプッシュします。
Terraformプロジェクト全体を一気に適用すると、ECRのリポジトリが空のため、Lambda作成時にエラーとなります。
planコマンドで問題なければECRのリソースを作成します。
terraform apply -var-file="terraform.tfvars" -target="aws_ecr_repository.example"
ECRにイメージをプッシュする
先に作成したECRにDockerイメージをプッシュします。
マネジメントコンソールのプッシュコマンドを表示ボタンを押下すると、プッシュ方法が記載されています。
- ECRにログインします。
aws ecr get-login-password --region ap-northeast-1 --profile <profile_name> | docker login --username AWS --password-stdin <accountID>.dkr.ecr.ap-northeast-1.amazonaws.com
- Dockerイメージにタグをつけます。
:以降がイメージタグになり、今回はlatestとなっています。
TerrafromのECRの設定でimage_tag_mutability = "IMMUTABLE"と記載しています。
これは、リポジトリ内のコンテナイメージタグの変更(上書き)を禁止する設定で、同じタグでの再プッシュが不可能になります。
docker tag sample-image:latest-01 <accountID>.dkr.ecr.ap-northeast-1.amazonaws.com/example-repo:latest
- タグ付けしたイメージをプッシュします。
docker push <accountID>.dkr.ecr.ap-northeast-1.amazonaws.com/example-repo:latest
無事イメージをプッシュできました。

すべてのリソースを作成する
残りのリソースもTerraformから作成します。
terraform apply -var-file="terraform.tfvars"
成功したらマネジメントコンソールでLambdaを確認してみましょう。
テストボタンを押すと、ステータスコード200とHello from Lambda container!が表示されました。


まとめ
無事にHello from Lambda container!を拝むことができました。
作成したリソースは不要な場合はterraform destroyで削除することをお忘れなく。
今回の作業でコンテナやLambdaに関して少し解像度があがった気がします。
皆さまも同じようなタスクが発生した際はこちらの記事を役立てていただけましたら非常にうれしい限りです。
こうすればもっと簡単であったり、言ってることおかしいという方がいらっしゃいましたら、
是非コメントいただければ幸いです。
ありがとうございました。

