LayerにGemを格納してAWS Lambda関数を成功させる方法

はじめに

AWS LambdaでRubyを使って実装しようとしたとき、Gemを使いたいことがよくあります。Gemを使う際にちょっとハマったので、解決方法を記します。

とりあえずGemの使用例としてActiveSupportを使った以下のプログラムを動かしてみたいと思います。

require 'active_support/all'

def lambda_handler(event:, context:)
    p 4.month.from_now
    "Hello Ruby Lambda"
end

これを動かそうとすると、ActiveSupportを読み込めずにLambda関数は失敗します。

Layerの作成

本件を解決するために、Layerを作成します。公式ドキュメントに以下の記述がありますのでそれを参考にします。

docs.aws.amazon.com

Gemfileを以下のように実装します。

# frozen_string_literal: true

source "https://rubygems.org"

gem 'activesupport'

任意の環境(Cloud9とか)で以下のコマンドを実行します。

bundle config set --local path 'vendor/bundle' && bundle install

これでvendor/bundle以下にGemファイルがインストールされるので、これをzipファイルとしてまとめます。

zip -r my_ruby_package.zip vendor

このzipファイルをLayerとして登録しておきます。関数にも紐付けしておきます。

環境変数の設定

上記のドキュメントに記載がありますが、Lambdaはレイヤーのコンテンツをその実行環境の/optディレクトリに読み込むようです。実際に中身を覗いてみると、/opt/vendor/bundle/ruby/3.2.0以下にGemが入っています。

このため、環境変数GEM_PATH/opt/vendor/bundle/ruby/3.2.0を指定しておきます。

実行

これで準備が整いました。関数を実行してみると成功します。

考察

以上の作業を行うことでGemをLayerに格納しつつ、Gemを使ったLambda関数を実行することができました。ちょっと前準備が多いのが面倒ですね。

今回はActiveSupportを試しましたが、RubyのGemにはC言語で実装したものなどが存在します。例えばMySQLPostgreSQLと接続するために使うものが該当します。これらのGemを使うときにはさらに作業が必要となりそうです。この解決方法については後日記します。