LoginSignup
3
1

SinatraをAWS Lambdaで動かす (Lambda Web Adapter 0.8.1 使用)

Last updated at Posted at 2024-02-01

AWS Lambda 上で、任意の Web アプリケーションフレームワークを動かせる「Lambda Web Adapter」が、バージョン 0.8.1 で HTTP 以外のイベントも受けられるようになりました。

ここでは、Ruby製Webアプリケーションフレームワーク「Sinatra」を、AWS Lambda + Lambda Web Adapter で動かす最小構成を紹介します。

1. 動作確認用の最小構成Sinatraアプリケーション

いたって普通のSinatraアプリですね。これが AWS Lambda でそのまま動作します。

app.rb (Sinatraアプリ)
require 'sinatra'

get '/' do
  logger.info params # QueryString
  'Hello! I am <b>Sinatra</b>.'
end

post '/' do
  logger.info params # QueryString and/or x-www-form-urlencoded
  logger.info request.body.read # e.g.) application/json
  'Post data recived.'
end

post '/events' do # for Non-HTTP Event Trigger
  logger.info request.body.read # Logging body
  'success' # w/ HTTP 200
end
Sinatra環境構築
mkdir -p sinatra_app1
cd sinatra_app1
bundle init
bundle add sinatra
bundle add rackup
ls
#=> Gemfile  Gemfile.lock  app.rb
動作確認
ls
#=> Gemfile  Gemfile.lock  app.rb
bundle exec ruby app.rb -p 8080
# CTRL+C で終了

# 別ターミナルから
curl localhost:8080/
#=> Hello! I am <b>Sinatra</b>.

Dockerfile 作成とビルド

先ほどの Sinatra アプリに Runtime である Ruby 本体を同梱してコンテナイメージを作成します。

Dockerfile
FROM public.ecr.aws/docker/library/ruby:3.3
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.1 /lambda-adapter /opt/extensions/lambda-adapter
WORKDIR /var/task
COPY ./ ./
RUN bundle install
CMD ["bundle", "exec", "ruby", "app.rb", "-o", "0.0.0.0", "-p", "8080"]
コンテナイメージのビルド
ls
#=> Dockerfile  Gemfile  Gemfile.lock  app.rb
docker build -t sinatra_app1 .
動作確認
docker images sinatra_app1
#=> REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
#=> sinatra_app1   latest    7d50536b75db   25 minutes ago   1.01GB
docker run -it --rm -p 8080:8080 sinatra_app1
# CTRL+C で終了

# 別ターミナルから
curl localhost:8080/
#=> Hello! I am <b>Sinatra</b>.

この後の作業

AWS Lambda で Amazon Elastic Container Registry(ECR) 上のコンテナを利用する方法と同じ手順です。

  1. Amazon ECR にレジストリを作成
  2. コンテナイメージに tag を付与
  3. Amazon ECR レジストリへコンテナイメージを push

${ACCOUNTID}${REGION} は読み替えてください。

1~3の手順
aws ecr create-repository --repository-name sinatra_app1_lambda #1
docker tag sinatra_app1:latest ${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com/sinatra_app1_lambda:latest #2
aws ecr get-login-password | docker login --username AWS --password-stdin ${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com #3a
docker push ${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com/sinatra_app1_lambda:latest #3b
コンテナイメージの確認
aws --output text ecr list-images --repository-name sinatra_app1_lambda
#=> IMAGEIDS        sha256:3bc6833093c4adaefddba0737501226fa02e9ac0e7ebe83c82b5111300f12639 latest

あとは、AWS Lambda の操作です。関数作成時に「コンテナイメージ」を参照するように設定します。関数のアーキテクチャは x86_64、メモリーは 512MB を割り当てましょう。

Lambda 関数の動作ログは CloudWatch Logs で確認できます。

トラブルシュート:

  • /usr/local/lib/ruby/3.3.0/rubygems.rb:165: [BUG] Segmentation fault at 0xffffffffffffffff が発生したら:
    • メモリー不足です。Lambda 関数へのメモリー割り当てを増やしてください。
  • INIT_REPORT Init Duration: xx.xx ms Phase: init Status: error Error Type: Extension.LaunchError が発生したら:
    • アーキテクチャーの不一致です。コンテナイメージ内のアーキテクチャーと、Lambda 関数のアーキテクチャーが一致しているか確認して、必要であれば Lambda 関数を再作成してください。

コンテナイメージの更新 = 関数の更新

docker build -t sinatra_app1 .
docker tag sinatra_app1:latest ${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com/sinatra_app1_lambda:latest
docker push ${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com/sinatra_app1_lambda:latest

あとは AWS Lambda 関数側で「新しいイメージをデプロイ」から、更新後のコンテナイメージを選んでデプロイすれば、更新されます。

あとがき

Non-HTTP トリガーは ここを見ると、 /events というパスへ Content-Type=application/json で HTTP POST される仕様ですね。Web アプリの要領で実装できます。
※ 個人的には lambda_handler() でいい気もしてますが。

コード例が examples にもあります

これと同じ内容が https://github.com/awslabs/aws-lambda-web-adapter/tree/main/examples/sinatra にあります。若干のディレクトリ構成の違いはありますが同じものです。

参考

[EoT]

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1