AWS LambdaでRailsを動かす
ついにLambdaがRubyをサポートしてくれましたね。
これまでLambdaを使う時はNodeやPythonを使ってきましたが、これからは一番書き慣れたRubyも使うことができるので嬉しい限りです。
Web上に「やってみた」記事は既にたくさんあるのですが、Railsを動かした系はまだ少なそうだったのでやってみました。
ゆくゆくは、Wheneverの代わりなどに使いたいという野望があります。
事前準備
- S3バケットを用意して
BUCKET_NAME
環境変数に入れておく - IAMユーザーを用意して
PROFILE_NAME
環境変数に入れておく
AWS SAM CLIのインストール
標準以外のGemを使う場合は、SAMを使ってカスタムランタイムをデプロイする必要があるので、CLIをインストールします。
Macの場合はbrewでインストールできます。
$ brew tap aws/tap
$ brew install aws-sam-cli$ sam --version
SAM CLI, version 0.10.0
Railsプロジェクトの作成
今回はとりあえず動かすところを目指すので、できるだけスリムにするためいろいろとskipします。
$ rbenv shell 2.5.3
$ rails new aws-lambda-rails --skip-coffee --skip-active-record --skip-action-cable --akip-active-storage --skip-bundle --skip-bootsnap
$ cd aws-lambda-rails/
bundle install
ネイティブ拡張があるGemを使う場合は、Lambdaと同等の環境でbundleする必要があります。
Dockerがインストールされていれば、以下のコマンドで一発です。いい時代ですね。
$ docker run -v `pwd`:`pwd` -w `pwd` -it lambci/lambda:build-ruby2.5 bundle --deployment
参考:https://forums.aws.amazon.com/thread.jspa?messageID=879802&tstart=0
lamba.rb
Lambda上で実行する処理を書きます。
今回はrake aboutするだけにします。
require_relative 'config/application'Rails.application.load_tasksdef handler(event:, context:)
Rake::Task['about'].invoke
end
template.yml
SAMでパッケージするためのYAMLを用意します。
Handler
に先程書いた lamda.handler
を指定しています。
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:
ExampleFunction:
Type: AWS::Serverless::Function
Properties:
Handler: lambda.handler
Runtime: ruby2.5
Timeout: 30
デプロイ
これで準備はOKです。SAMでパッケージ&デプロイします。
$ sam package --template-file template.yml \
--s3-bucket $BUCKET_NAME \
--output-template-file packaged-template.yml \
--profile $PROFILE_NAME
$ sam deploy --template-file packaged-template.yml \
--region ap-northeast-1 \
--stack-name aws-lambda-rails \
--capabilities CAPABILITY_IAM \
--profile $PROFILE_NAME
実行
AWSコンソール上で実行します。
環境変数を指定して…
テスト!
無事、 rake about
の結果が表示されています。
まとめ
実用的な処理はしていませんが、RailsをLambda上で動かすことができました。
Dockerのおかげで思ったより手軽にできました。
今後なにか定期的な処理を書きたいニーズが出てきたら、バリバリRubyで書いていきたいと思います。
ソースコード
こちらです。
※ packaged-template.yml
と vendor/bundle
は gitignoreしています。