今回は、Terraformを使用してDockerイメージをLambdaへデプロイする手順を紹介していこうと思います。
本記事では、TerraformからECRへDockerイメージをプッシュし、それをLambdaで実行するシンプルな構成をまとめています。
まず簡単にTerraformについてまとめていきます。
一言で言えば、IaCの一種でクラウドリソースをコード化することができるツールです。Terraform
は、AWS、Azure、GCP など、1000 以上のプロバイダーに対応しており、異なるプロバイダーのリソースをHCL(HashiCorp Configuration Language) という言語で管理できます。
Terraformを使用する上で覚えていきたいコマンドは以下の5つです。
-
terraform init
- Terraformプロジェクトの初期化を行うコマンド
-
プロバイダーのダウンロードとインストール
・バックエンドの初期化
・モジュールのダウンロード
をしてくれます
-
terraform plan
- 現在の状態から目的の状態への変更内容を確認するコマンド
-
terraform apply
- インフラストラクチャに変更を適用するコマンド
- 実行後は、
plan
の結果が表示され、続行の確認が求められます
-
terraform destroy
- Terraform で作成したすべてのリソースを削除するコマンド
-
terraform fmt
- Terraformの設定ファイルを標準的なフォーマットに整形するコマンド
- インデントの調整・改行の統一・スペースの調整をしてくれます
本記事では、リージョンを「ap-northeast-1(東京)」に設定して、Terraformを使った Lambdaデプロイを構築していきます。
なお、実際に使用したコードや構成ファイルは以下のGitHubリポジトリで公開しています。
Dockerfileの作成
まずは、Lambda関数のベースとなるDockerイメージを用意します。
今回は Python 3.13 の Lambda ランタイムを使用します。api
ディレクトリを作成し、以下の内容で Dockerfileを作成してください。
FROM public.ecr.aws/lambda/python:3.13
COPY app.py ${LAMBDA_TASK_ROOT}
CMD [ "app.handler" ]
-
--platform=linux/amd64
は、Apple M1/M2 チップなどのARM環境でビルドエラーを避けるための指定 -
LAMBDA_TASK_ROOT
は、AWS Lambdaが実行時にコードを読み込むディレクトリ
app.pyの作成
次に、Lambda 関数の処理本体となる app.py を作成します。
先ほどのDockerfileではこのファイルをコンテナ内にコピーし、handler
関数をエントリーポイントとしています。
以下の内容でapi/app.py
を作成してください。
import json
def handler(event, context):
print(event)
return {
"statusCode": 200,
"body": json.dumps({ "message": "Hello, Lambda!" })
}
Lambdaが正常に動作すると "Hello, Lambda!"
というメッセージが返されるシンプルな構成にしています。
今回は Pythonの標準ライブラリのみを使用しているため、requirements.txt
の作成やパッケージのインストールは行っていません。
ローカルで関数をテストする
では、実際に機能するかをdocker
をビルドして確かめてみましょう。
以下の手順に従って確認していきましょう。
cd api
docker build -t api .
docker run -p 9000:8080 api
curl -XPOST "" -d '{"payload":"Hello, Lambda!"}'
以下のJSONが得られたら、テスト成功です。
{
"statusCode": 200,
"body": "{\"message\": \"Hello, Lambda!\"}"
}
今回は以下の2つのファイルを用意します。
-
main.tf
- Terraform の基本設定用のファイル
- どのクラウド(AWS)・ツール(Docker)を使うかを記述しています
-
api.tf
- ECRとLambdaを構築・デプロイするためのファイル
main.tfについて
main.tfファイルでは、Terraformがどのプロバイダ(AWSやDockerなど)を使用するか、また AWS の接続先リージョンを指定しています。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
-
required_providers
- aws やdocker はTerraformで操作したいサービス群を意味します
-
source
はそのプロバイダがどこから提供されているか(hashicorp/aws) -
version
は互換性のあるバージョンを指定しており、たとえば “~> 5.0” は 5.x 系の最新版を自動で使うという意味です
-
provider
- どのリージョンのAWSに対してリソースを作成するかを指定します
api.tfについて
api.tfファイルでは、以下の3つの処理をまとめて行っています
- DockerイメージのビルドとECRへのプッシュ
- Lambda関数の作成
- Dockerレジストリへの認証設定(Terraform が ECR に push するため)
data "aws_ecr_authorization_token" "token" {}
data "aws_caller_identity" "current" {}
provider "docker" {
registry_auth {
address = "${data.aws_caller_identity.current.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com"
username = data.aws_ecr_authorization_token.token.user_name
password = data.aws_ecr_authorization_token.token.password
}
}
module "lambda_function" {
source = "terraform-aws-modules/lambda/aws"
function_name = "python-api"
create_package = false
image_uri = module.docker_image.image_uri
package_type = "Image"
depends_on = [module.docker_image]
}
module "docker_image" {
source = "terraform-aws-modules/lambda/aws//modules/docker-build"
create_ecr_repo = true
ecr_repo = "python-api"
use_image_tag = true
image_tag = "1.0"
triggers = {
redeployment = timestamp()
}
source_path = "../api"
}
こちらのファイルでは以下のポイントに気をつけてください。
Docker イメージを使う Lambda 関数の定義
module "lambda_function" {
source = "terraform-aws-modules/lambda/aws"
function_name = "python-api"
create_package = false
image_uri = module.docker_image.image_uri
package_type = "Image"
depends_on = [module.docker_image]
}
-
create_package = false
- 今回はzipではなくDockerイメージを使うため、こちらは必須
-
image_uri
- ECRに登録されたDockerイメージを指定
-
depends_on
- ビルドされたイメージが先に必要なので依存関係を明示
Dockerレジストリの認証
provider "docker" {
registry_auth {
address = "${data.aws_caller_identity.current.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com"
username = data.aws_ecr_authorization_token.token.user_name
password = data.aws_ecr_authorization_token.token.password
}
}
-
Docker CLI
ではなくTerraformが docker push するための認証設定です -
username
とpassword
には、AWSから取得したECR認証トークンの値を使用しています - address(ECR のURL)に関しては
${data.aws_caller_identity.current.account_id}
を使って動的にアカウントIDを取得しています- もちろん、ここは “123456789012.dkr.ecr.ap-northeast-1.amazonaws.com” のように手動で書いても問題ありませんが、複数人で使う場合・GitHubでソースコードを管理する場合は自動化しておく方が安全です
では、ここから実際にTerraformを使ってLambda
のデプロイ作業を行っていきます。
今回は、AWS CloudShellを利用して作業を進めました。CloudShell
は AWS マネジメントコンソールからすぐに開けて、IAMロールに紐づく認証情報が自動で使えるため、Terraform の初期実行にも非常に便利です。
Step.1 CloudShellでTerraformのセットアップ
wget https://releases.hashicorp.com/terraform/1.11.4/terraform_1.11.4_linux_amd64.zip
sudo unzip terraform_1.11.4_linux_amd64.zip -d /usr/local/bin/
terraform -version
Step.2 GitHub から Terraform ファイルを取得
先ほど作成したものを、GitHub上におき、そちらをCloudShell上でgit clone
を使って取得します。
git clone https://github.com/your-username/your-repo-name.git
cd your-repo-name
Step.3 Terraformでリソースをデプロイ
① Terraformの初期化
main.tf
, api.tf
ファイルがあることを確認し、以下のコマンドを実行してください。
コマンド入力後は、以下の出力があればinit
の完了です。
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/
ディレクトリにダウンロードされ、Terraformの実行準備が整います。
もし、init
実行時に"no space left on device"
エラーが発生した場合は、以下の記事を参考に対応してください。
② デプロイの実行!
terraform apply --auto-approve
--auto-approve
を付けることで、yesの確認を省略して自動で処理が進みます。
実行すると以下のような感じでモジュールが作成されていきます。
以下のメッセージが出力されれば、Terraformでの実行は完了です。
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
デプロイできたか確認
ECRへ移動して、実際にpython-apiがあるか確認してください。
次は、Lambdaへ移動しpython-api
関数がECRのイメージを参照していれば、デプロイ完了です!
新しいイベントを実行してみる
デプロイが完了したら、Lambda 関数が正しく動作するかどうかをテストしてみましょう。
まずは、AWSマネジメントコンソール上でLambdaに移動し、関数ページの右上にある「テスト
」ボタンをクリックします。
以下の画像の通りに進め、イベント名は任意で大丈夫です。JSONはデフォルトのままで問題ありません。
「テスト
」を実行すると、以下のように Lambda のレスポンス結果が表示されます。
成功すれば、"Hello, Lambda!"
というメッセージが返ってくることを確認できます。
これで、Lambda関数がDockerイメージをもとに正しく動作していることが確認できました!
なお、このイベント実行の内容は CloudWatch Logs にも記録されます。
必要に応じて CloudWatch側のログを確認しながら作業を進めるのもおすすめです。
最後に検証終了後は、リソースを以下のコマンドで全て削除しておきましょう。
terraform destroy --auto-approve
今回は、Terraform を使って Docker イメージを AWS Lambda にデプロイする手順を紹介しました。
手動でリソースを構築するのではなく、コード化して管理することでインフラの再現性・可搬性・チームでの共有性が大きく向上することを体感できました。
引き続きTerraformの学習を頑張っていこうと思います。
最後まで読んでいただきありがとうございました!
Views: 2