Terraform AWS modulesでコンテナLambdaをデプロイする実装方法

Terraform AWS modulesでコンテナLambdaをデプロイする実装方法

2025.12.31

歴史シミュレーションゲーム好きのくろすけです!

StepFunctions を再キャッチアップする中で Terraform で Lambda をサクッと作成してみたので思ったことなども含め記事にしてみます。

以前ちょっとだけ terraform-aws-modules を使ってみたのですが、設計思想が若干合わないと思った箇所があり、あまり使用していませんでした。
ですが改めて車輪の再発明をしているのは時間の無駄だなと思い、再度使ってみることにしました。

概要

本記事では、terraform-aws-modules/lambda/aws モジュールを使用して、Dockerコンテナイメージベースのシンプルなダミー用Lambda関数をデプロイしてみます。

やってみた

1. ディレクトリ構成の準備

まず、以下のようなディレクトリ構成を準備しました。

.
├── infra/
│   └── services/
│       └── lambda/
│           └── krsk/
│               ├── main.tf
│               ├── provider.tf
│               ├── terraform.tfvars
│               └── variables.tf
└── lambda/
    └── dummy/
        ├── app.py
        └── Dockerfile

2. Lambda関数のコード作成

シンプルなダミーLambda関数を作成します。

lambda/dummy/app.py:

import json


def lambda_handler(event, context):
    """
    Simple dummy AWS Lambda function.
    """
    # Log the received event
    print(f"Received event: {json.dumps(event)}")

    # Create a response
    response = {
        "statusCode": 200,
        "body": json.dumps({"message": "Hello from Dummy Lambda!", "event": event}),
    }

    return response

受け取ったイベントをログに出力し、シンプルなレスポンスを返すだけの関数です。

3. Dockerfileの作成

次に、Lambda関数をコンテナ化するためのDockerfileを作成します。

lambda/dummy/Dockerfile:

FROM public.ecr.aws/lambda/python:3.12

COPY app.py ${LAMBDA_TASK_ROOT}

CMD [ "app.lambda_handler" ]

4. Terraformコードの作成

terraform-aws-modulesを使ってLambda関数をデプロイするTerraformコードを作成します。

infra/services/lambda/krsk/main.tf:

locals {
  lambda_source_dir = "${path.module}/../../../../lambda/dummy"

  source_hash = sha256(join("", [
    for f in fileset(local.lambda_source_dir, "**") :
    filesha256("${local.lambda_source_dir}/${f}")
  ]))
}

module "docker_image" {
  source = "terraform-aws-modules/lambda/aws//modules/docker-build"

  create_ecr_repo = true
  ecr_repo        = "${var.sys_name}-${var.env}-repo"

  use_image_tag = true
  image_tag     = substr(local.source_hash, 0, 12)

  source_path = local.lambda_source_dir
}

module "lambda_function" {
  source = "terraform-aws-modules/lambda/aws"

  function_name  = "${var.sys_name}-${var.env}-lambda"
  create_package = false

  image_uri    = module.docker_image.image_uri
  package_type = "Image"

  architectures = ["arm64"]

  timeout     = 60
  memory_size = 512

  tracing_mode = "Active"

  publish = true

  attach_policy = true
  policy        = "arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy"

  tags = {
    Environment = var.env
    Name        = "${var.sys_name}-${var.env}-lambda"
  }

  depends_on = [module.docker_image]
}

module "lambda_alias" {
  source = "terraform-aws-modules/lambda/aws//modules/alias"

  name = var.env

  function_name    = module.lambda_function.lambda_function_name
  function_version = module.lambda_function.lambda_function_version

  description = "environment alias (krsk)"
}

コードのポイント

以下の2点でLambdaエイリアスベースのデプロイを実現しています。

1. Lambdaソースディレクトリ自動変更検出

locals {
  ...(中略)...

  source_hash = sha256(join("", [
    for f in fileset(local.lambda_source_dir, "**") :
    filesha256("${local.lambda_source_dir}/${f}")
  ]))
}

module "docker_image" {
  ...(中略)...

  use_image_tag = true
  image_tag     = substr(local.source_hash, 0, 12)


  ...(中略)...
}

Lambdaソースディレクトリ内の全ファイルのハッシュ値を計算し、コードが変更されたことをハッシュ値で検出できるようになっています。
ハッシュ値を image_tag に使用することで、結果的にLambdaソースディレクトリ内の変更を検知しDockerイメージのビルド、ECRへのプッシュを自動で実行する処理を実現しています。

3. lambdaモジュール

module "lambda_function" {
  ...(中略)...

  publish = true

  ...(中略)...
}

module "lambda_alias" {
  ...(中略)...

  function_name    = module.lambda_function.lambda_function_name
  function_version = module.lambda_function.lambda_function_version

  ...(中略)...
}

publish を true にすることで自動で新しいバージョンを発行し、最新バージョンをエイリアスにアタッチします。

やってみてわかったこと

  • LambdaのソースコードとインフラのデプロイをTerraformで一気通貫に実行できる
  • 上記のため、アプリとインフラで一つのCI/CDとしてまとめることができる
  • 簡単な検証用の環境としては使い勝手が良さそう

ただし、

  • システム運用中の環境には向かないケースが多いかも
    • ゴールデンイメージを使い回すなら、アプリとインフラのライフサイクルが異なってくる
  • 運用中の環境としては向いてなさそう

あとがき

terraform-aws-modulesは、Terraformによる開発を簡素化してくれる素晴らしいツールだと改めて実感しました。
ただし使ってみてどこまでモジュールの機能を活用するかはケースバイケースで考慮する必要があることも実感しました。

terraform-aws-modulesを使ってみて効率的に開発できることを実感したので、今後は積極的に活用していこうと思います。

以上、くろすけでした!

この記事をシェアする

FacebookHatena blogX

関連記事