Ruby で実装した Lambda 関数 を CDK でデプロイして動作させるメモ
CDK でさくっとデプロイしたは良いが、依存する Gem がインストールされていない
Lambda 関数内で以下の Gem を利用しているが、それがデプロイ対象に入っていないらしい?
{
"errorMessage": "cannot load such file -- mail",
"errorType": "Init<LoadError>",
"stackTrace": [
"<internal:/var/lang/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require'",
"<internal:/var/lang/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require'",
"/var/task/mail_receiver.rb:3:in `<top (required)>'",
"<internal:/var/lang/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require'",
"<internal:/var/lang/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require'",
"/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:48:in `run'",
"/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:221:in `bootstrap_handler'",
"/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:203:in `start'",
"/var/runtime/index.rb:4:in `<main>'"
]
}
解決してくれそうな Construct Library がある
If a file named "Gemfile" exists directly inside sourceDirectory, the dependency gems are bundled using Bundler. Bundling is performed inside a Docker container using the Lambda builder images privided by AWS. The bundlerConfig prop may have the without field to specify a colon-separated list of gem groups to skip installation.
Install
npm i cdk-lambda-ruby
Error: GitIgnoreStrategy expects an absolute file path
cdk diff
したらなんかエラーが
スタックトレース(一部改変済み)
Error: Failed to bundle asset SesMailRecieverStack/MailHandler/MailHandler/Code/Stage, bundle output is located at /Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/asset.2a38ebf16e8e97acb132dd55f881188a8e0022a6b0601a8f29315cdbc825511e-error: Error: GitIgnoreStrategy expects an absolute file path
at AssetStaging.bundle (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:2:619)
at AssetStaging.stageByBundling (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:5297)
at stageThisAsset (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:2728)
at Cache.obtain (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/private/cache.js:1:242)
at new AssetStaging (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:3125)
at new Asset (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-s3-assets/lib/asset.js:1:1141)
at AssetCode.bind (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-lambda/lib/code.js:5:3487)
at new Function (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-lambda/lib/function.js:1:9422)
at new RubyFunction (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/cdk-lambda-ruby/lib/function.ts:32:5)
at new MailHandler (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/lib/mail_handler.ts:23:20)
メッセージは
Error: GitIgnoreStrategy expects an absolute file path
RubyFunction のコード
cdk-lambda-ruby 側の git ignore に関連しそうなコード
core 側 tryBundle
を呼び出している
IgnoreStrategy
ここに渡す absoluteRootPath
が絶対パスになっていない?
absoluteRootPath
は
copyDirectory()
の4つ目の引数 rootDir
として受け取ったものを渡している
cdk-lambda-ruby では rootDir
を渡していない
copyDirectory で rootDir
がなければ srcDir
を割り当てているはず
cdk-lambda-ruby の this.sourceDirectory
が何を指しているか?
RubyFunction
コンストラクタに渡しているプロパティの sourceDirectory
ここの sourceDirectory
が絶対パスでなければならないということかもしれない
this.handler = new lambdaRuby.RubyFunction(this, 'MailHandler', {
runtime: lambda.Runtime.RUBY_3_3,
handler: 'mail_receiver.lambda_handler',
sourceDirectory: 'lambda',
});
cdk-lambda-ruby の example と比較
以下のような修正でこのエラーは解消した
- sourceDirectory: 'lambda',
+ sourceDirectory: path.join(__dirname, '../lambda'),
bundler のワーニング
Your bundle only supports platforms ["arm64-darwin-22"] but your local platform
is aarch64-linux. Add the current platform to the lockfile with
`bundle lock --add-platform aarch64-linux` and try again.
bundle lock --add-platform aarch64-linux
を実行したら Gemfile.lock が以下のように修正された
PLATFORMS
+ aarch64-linux
arm64-darwin-22
Error: docker exited with status 16
なんか Docker Image のビルドで落ちた?
Error: Failed to bundle asset SesMailRecieverStack/MailHandler/MailHandler/Code/Stage, bundle output is located at /Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/asset.7cd5b91369ef89105a48c551878b2fb6010786cb95f1fa0d7e3f2eb4284e1f11-error: Error: docker exited with status 16
--> Command: docker run --rm -u "501:20" -v "/Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/asset.7cd5b91369ef89105a48c551878b2fb6010786cb95f1fa0d7e3f2eb4284e1f11:/asset-output:delegated" -v "/Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/.cache/lambda-ruby:/asset-cache:delegated" --env "BUNDLING_OUTPUT_DIR=/asset-output" --env "BUNDLING_CACHE_DIR=/asset-cache" --env "BUNDLE_WITHOUT=development:test" -w "/asset-output" "public.ecr.aws/sam/build-ruby3.3" "/bin/sh" -euc "export HOME=$(mktemp -d)\n\nexport MAKEFLAGS=-j$(nproc)\n\nexport BUNDLE_USER_CACHE=$BUNDLING_CACHE_DIR/bundler\nexport BUNDLE_CLEAN=true\nexport BUNDLE_DEPLOYMENT=true\nexport BUNDLE_GLOBAL_GEM_CACHE=true\nexport BUNDLE_PATH=vendor/bundle\nexport BUNDLE_RETRY=3\n\nif test -f Gemfile; then\n bundle config set --local deployment \"$BUNDLE_DEPLOYMENT\"\n bundle config set --local path \"$BUNDLE_PATH\"\n bundle config set --local without \"$BUNDLE_WITHOUT\"\n exec bundle install\nelse\n exec rm -rf vendor/bundle\nfi\n"
at AssetStaging.bundle (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:2:619)
at AssetStaging.stageByBundling (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:5297)
at stageThisAsset (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:2728)
at Cache.obtain (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/private/cache.js:1:242)
at new AssetStaging (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:3125)
at new Asset (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-s3-assets/lib/asset.js:1:1141)
at AssetCode.bind (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-lambda/lib/code.js:5:3487)
at new Function (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-lambda/lib/function.js:1:9422)
at new RubyFunction (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/cdk-lambda-ruby/lib/function.ts:32:5)
at new MailHandler (/Users/cdk-example/hoge-cdk/ses-mail-reciever/lib/mail_handler.ts:24:20)
cdk-lambda-ruby 使うと Docker Image もビルドするようになってる?
そのあたりの挙動の違いも気になる
README.md に書いていた
Bundling is performed inside a Docker container using the Lambda builder images privided by AWS.
実行された docker コマンド
docker run --rm -u "501:20" \
-v "/Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/asset.7cd5b91369ef89105a48c551878b2fb6010786cb95f1fa0d7e3f2eb4284e1f11:/asset-output:delegated" \
-v "/Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/.cache/lambda-ruby:/asset-cache:delegated" \
--env "BUNDLING_OUTPUT_DIR=/asset-output" \
--env "BUNDLING_CACHE_DIR=/asset-cache" \
--env "BUNDLE_WITHOUT=development:test" \
-w "/asset-output" \
"public.ecr.aws/sam/build-ruby3.3" "/bin/sh" -euc
"export HOME=$(mktemp -d)
export MAKEFLAGS=-j$(nproc)
export BUNDLE_USER_CACHE=$BUNDLING_CACHE_DIR/bundler
export BUNDLE_CLEAN=true
export BUNDLE_DEPLOYMENT=true
export BUNDLE_GLOBAL_GEM_CACHE=true
export BUNDLE_PATH=vendor/bundle
export BUNDLE_RETRY=3
if test -f Gemfile; then
bundle config set --local deployment \"$BUNDLE_DEPLOYMENT\"
bundle config set --local path \"$BUNDLE_PATH\"
bundle config set --local without \"$BUNDLE_WITHOUT\"
exec bundle install
else
exec rm -rf vendor/bundle
fi
"
Bundler のワーニングと思ってたのがエラーメッセージだったらしい
上記対応したら、エラーも解消した
動作結果の確認
Lambda のコンソールを見て vendor/bundle
に gem などが格納されていることを確認した
Gemfile に gem を追加したらエラーになる
試しに "prawn" を追加してみた
diff --git a/ses-mail-reciever/lambda/Gemfile b/ses-mail-reciever/lambda/Gemfile
index 91579df..bb56f49 100644
--- a/ses-mail-reciever/lambda/Gemfile
+++ b/ses-mail-reciever/lambda/Gemfile
@@ -4,3 +4,4 @@ source "https://rubygems.org"
gem "mail"
gem 'jwt'
+gem 'prawn'
すると cdk diff
でエラーになった
You are trying to install in deployment mode after changing
your Gemfile. Run `bundle install` elsewhere and add the
updated Gemfile.lock to version control.
If this is a development machine, remove the /asset-output/Gemfile freeze
by running `bundle config unset deployment`.
The dependencies in your gemfile changed
You have added to the Gemfile:
* prawn
原因
bundle install
実行していないため、Gemfile
と Gemfile.lock
の整合性が取れていない状態だった。
対応
Gemfile
を更新したら ./lambda
ディレクトリで以下を実行することで Gamfile.lock
を更新する
bundle install
Error: Cannot retrieve value from context provider key-provider since account/region are not specified at the stack level.
cdk diff
を実行すると以下のようなエラー
Error: Cannot retrieve value from context provider key-provider since account/region are not specified at the stack level. Configure "env" with an account and region when you define your stack.See https://docs.aws.amazon.com/cdk/latest/guide/environments.html for more details.
原因
環境変数 AWS_PROFILE
などの設定が抜けていた
対応
環境変数など AWS CLI が動作する状態にする