Techioz Blog

Ruby Postgres gem の AWS Lambda レイヤーが機能しない

概要

この投稿をガイドとして使用して、Ruby 上で実行される AWS Lambda 用の Postgres レイヤーを構築しようとしていますが、機能しません。

これが Dockerfile です。これを機能させるために、RUN バンドル設定cache_all true と RUN バンドルパッケージを追加しました。 RUN env ARCHFLAGS=“-arch aarch64” gem install pg も試しましたが、まだ機能しませんでした。

FROM public.ecr.aws/lambda/ruby:3.2

RUN yum install -y amazon-linux-extras \
    && amazon-linux-extras enable postgresql14 \
    && yum group install "Development Tools" -y

RUN yum install -y postgresql postgresql-devel

ADD Gemfile Gemfile.lock ${LAMBDA_TASK_ROOT}

ENV GEM_HOME=${LAMBDA_TASK_ROOT}

RUN bundle config cache_all true
RUN bundle config set path 'vendor/bundle'

RUN bundle install
RUN bundle package

これがスクリプトです

#!/bin/sh -e

DIST_DIR="pg"
rm -rf $DIST_DIR
mkdir -p "$DIST_DIR/lib"
mkdir -p "$DIST_DIR/ruby/gems"

cd "$SOURCE_DIR" >/dev/null || exit

docker build -t ruby-builder -f Dockerfile .
CONTAINER=$(docker run -d ruby-builder)

# See https://northsail.io/articles/aws-lambda-ruby-2-7-pg-gem-libldap-error
# for what to libpq binaries to copy for Amazon Linux 2
docker cp \
  $CONTAINER:/usr/lib64/libpq.so.5.14 \
  $DIST_DIR/lib/libpq.so.5

docker cp \
  $CONTAINER:/usr/lib64/libldap_r-2.4.so.2.10.7 \
  $DIST_DIR/lib/libldap_r-2.4.so.2

docker cp \
  $CONTAINER:/usr/lib64/liblber-2.4.so.2.10.7 \
  $DIST_DIR/lib/liblber-2.4.so.2

docker cp \
  $CONTAINER:/usr/lib64/libsasl2.so.3.0.0 \
  $DIST_DIR/lib/libsasl2.so.3

docker cp \
  $CONTAINER:/usr/lib64/libssl3.so \
  $DIST_DIR/lib/

docker cp \
  $CONTAINER:/usr/lib64/libsmime3.so \
  $DIST_DIR/lib/

docker cp \
  $CONTAINER:/usr/lib64/libnss3.so \
  $DIST_DIR/lib/

docker cp \
  $CONTAINER:/usr/lib64/libnssutil3.so \
  $DIST_DIR/lib/

docker cp \
  $CONTAINER:/var/task/vendor/bundle/ruby/3.2.0 \
  $DIST_DIR/ruby/gems/3.2.0

docker stop $CONTAINER
docker rm $CONTAINER

生成されたフォルダー ツリーは次のようになります。

.
├── lib
└── ruby
    └── gems
        └── 3.2.0
            ├── bin
            ├── build_info
            ├── cache
            ├── doc
            ├── extensions
            │   └── aarch64-linux
            │       └── 3.2.0
            ├── gems
            │   ├── bundler-2.4.17
            │   │   ├── exe
            │   │   └── lib
            │   └── pg-1.5.4
            │       ├── certs
            │       ├── ext
            │       ├── lib
            │       ├── misc
            │       ├── rakelib
            │       ├── sample
            │       └── translation
            ├── plugins
            └── specifications

これは、レイヤー内の gem が機能しているかどうかをテストするラムダ関数です。

require 'json'
require 'pg'

def lambda_handler(event:, context:)
    { statusCode: 200, body: {postgres_client_version: PG.library_version}.to_json }
end

そして、これがエラーメッセージです:

Test Event Name
test

Response
{
  "errorMessage": "cannot load such file -- pg",
  "errorType": "Init<LoadError>",
  "stackTrace": [
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'",
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'",
    "/var/task/lambda_function.rb:2:in `<top (required)>'",
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'",
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'"
  ]
}

Function Logs
Ignoring pg-1.5.4 because its extensions are not built. Try: gem pristine pg --version 1.5.4
Init error when loading handler lambda_function.lambda_handler
{
  "errorMessage": "cannot load such file -- pg",
  "errorType": "Init<LoadError>",
  "stackTrace": [
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'",
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'",
    "/var/task/lambda_function.rb:2:in `<top (required)>'",
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'",
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'"
  ]
}
INIT_REPORT Init Duration: 324.56 ms    Phase: init Status: error   Error Type: Runtime.ExitError
Ignoring pg-1.5.4 because its extensions are not built. Try: gem pristine pg --version 1.5.4
Init error when loading handler lambda_function.lambda_handler
{
  "errorMessage": "cannot load such file -- pg",
  "errorType": "Init<LoadError>",
  "stackTrace": [
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'",
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'",
    "/var/task/lambda_function.rb:2:in `<top (required)>'",
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'",
    "<internal:/var/lang/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:86:in `require'"
  ]
}
INIT_REPORT Init Duration: 2500.61 ms   Phase: invoke   Status: error   Error Type: Runtime.ExitError
START RequestId: 2ab0555b-bde9-4cb1-a0d4-ee0d2fe2d0b1 Version: $LATEST
Unknown application error occurred
Runtime.Unknown
END RequestId: 2ab0555b-bde9-4cb1-a0d4-ee0d2fe2d0b1
REPORT RequestId: 2ab0555b-bde9-4cb1-a0d4-ee0d2fe2d0b1  Duration: 2520.07 ms    Billed Duration: 2521 ms    Memory Size: 128 MB Max Memory Used: 16 MB

PG のネイティブ拡張機能がインストールされていないか、別のアーキテクチャ用にインストールされているようですが、現時点ではそれを修正する方法がわからず、かなり混乱しています。

これを機能させる方法についてのアドバイスをいただければ幸いです。 ありがとう。

解決策

別の Docker イメージを使用すると機能しました。

FROM public.ecr.aws/sam/build-ruby3.2:latest-x86_64

どうやら、以前のものはアーキテクチャが異なっており、間違った依存関係がインストールされていたようです。