こんにちは。今年こそは AWS SA プロフェッショナルを受験するぞ!と息巻いてる吉岡です。(受かるとは言ってない)
さて、かれこれ一年以上前になりますが、AWS Lambda でコンテナイメージが使えるようになったようです。
AWS Lambda の新機能 – コンテナイメージのサポート
今更ですが、先日、Ruby を使ったカスタムコンテナ(自分で書いた Dockerfile)で AWS Lambda(以下 Lambda)を動かしてみたので、実行方法を紹介したいと思います。
これまでは例えば、Lambda(Ruby runtime)で DB(MySQL, PostgreSQL) を扱うために Gem をインストールしようとすると、合わせてミドルウェアも必要になるため、設定や管理が非常に手間がかかりました。
参照: AWS Lambda Ruby 2.7 で PostgreSQL のコマンドを実行する方法
今回の新機能のおかげで、ミドルウェアを含めた環境ごとコンテナイメージにすることで簡単に DB を扱うことができるようになりました。もう少しわかりやすく書くと、Lambda で Rails を動かすことも割と簡単にできるようになりました!これによって rails コマンド(rails task など)を利用した処理などもサーバーレスで簡単に実行できるようになります!!
そこで今回は Lambda を Redmine の Docker イメージで起動し、rails コマンドを実行してみます。
※ 今回、ベースイメージは DockerHub 公式の redmine:4.2.3 を使用します。
参照: Redmine - Official Image | Docker Hub(リンク)
また、 DB は SQLite3 を使用し、コンテナイメージに含めています。(通常ではあり得ない運用ですが、動作確認ということで簡略化しています。)
以下、必要になります。
AWS SAM
バージョン: 1.37.0
インストール方法は以下のドキュメントをご確認ください。
参照: AWS SAM CLI のインストール
また、AWS SAM のインストールの際に AWS アカウントの作成や Docker のインストールなど必要に応じて作業してください。
それでは早速作業していきます。
sam init
を実行して必要ファイルの生成をします。
以下、実行サンプルです。
$ sam init Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Cloning from https://github.com/aws/aws-sam-cli-app-templates Choose an AWS Quick Start application template 1 - Hello World Example 2 - Multi-step workflow 3 - Serverless API 4 - Scheduled task 5 - Standalone function 6 - Data processing 7 - Infrastructure event management 8 - Machine Learning Template: 1 Use the most popular runtime and package type? (Nodejs and zip) [y/N]: Which runtime would you like to use? 1 - dotnet5.0 2 - dotnetcore3.1 3 - dotnetcore2.1 4 - go1.x 5 - java11 6 - java8.al2 7 - java8 8 - nodejs14.x 9 - nodejs12.x 10 - nodejs10.x 11 - python3.9 12 - python3.8 13 - python3.7 14 - python3.6 15 - python2.7 16 - ruby2.7 17 - ruby2.5 Runtime: 16 What package type would you like to use? 1 - Zip 2 - Image Package type: 2 Based on your selections, the only dependency manager available is bundler. We will proceed copying the template using bundler. Project name [sam-app]: rails-sample ----------------------- Generating application: ----------------------- Name: rails-sample Base Image: amazon/ruby2.7-base Architectures: x86_64 Dependency Manager: bundler Output Directory: . Next steps can be found in the README file at ./rails-sample/README.md Commands you can use next ========================= [*] Create pipeline: cd rails-sample && sam pipeline init --bootstrap [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
以下、実行時の選択肢です。
Which template source would you like to use? 1 - AWS Quick Start Templates Choose an AWS Quick Start application template 1 - Hello World Example Which runtime would you like to use? 16 - ruby2.7 こちらは後で書き換えますが、とりあえず ruby2.7 を選択します。 What package type would you like to use? 2 - Image 今回の1番の肝です。2 の Image を選択します。 Project name [sam-app]: rails-sample 名前は任意です。 上記実行後、以下のようなファイルが作成されていることを確認します。
無事に実行が終わりますと、以下のようにファイルとディレクトリが作成されます。
.
├── events
│ └── event.json
├── Gemfile
├── hello_world
│ ├── app.rb
│ ├── Dockerfile
│ └── Gemfile
├── README.md
├── template.yaml
└── tests
└── unit
└── test_handler.rb
続けて作成されたファイルを編集していきます。
template.yaml
AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: > rails-sample Sample SAM Template for rails-sample Globals: Function: Timeout: 120 MemorySize: 512 Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: PackageType: Image Architectures: - x86_64 Metadata: DockerTag: rails-v1 DockerContext: ./hello_world Dockerfile: Dockerfile Outputs: HelloWorldFunction: Description: "Hello World Lambda Function ARN" Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for Hello World function" Value: !GetAtt HelloWorldFunctionRole.Arn
template.yamlのポイントとして、Rails の起動と処理の実行に少し時間がかかるため、Timeout(lambda のタイムアウト)を少し長めにしておく必要があります。
Globals: Function: Timeout: 120 MemorySize: 512
hello_world/Dockerfile
FROM redmine:4.2.3 RUN gem install aws_lambda_ric ARG FUNCTION_DIR="/usr/src/redmine" WORKDIR ${FUNCTION_DIR} COPY app.rb ${FUNCTION_DIR} RUN : "database.ymlを作成" && { \ echo "production:"; \ echo " adapter: 'sqlite3'"; \ echo " host: 'localhost'"; \ echo " database: 'sqlite/redmine.db'"; \ echo " username: 'redmine'"; \ echo " password: ''"; \ echo " port: ''"; \ echo " encoding: 'utf8'"; \ } | tee ${FUNCTION_DIR}/config/database.yml RUN echo 'config.logger = Logger.new("tmp/production.log")' > config/additional_environment.rb RUN bundle install RUN rails generate_secret_token # 注)今回はサンプルのためコンテナイメージにDBを含めています。 RUN rails db:create RUN rails db:migrate ENTRYPOINT ["/usr/local/bundle/bin/aws_lambda_ric"] CMD ["app.lambda_handler"]
Dockerfileのポイントとしては lambda で起動するための Gem をインストールして、ENTORYPOINT
で aws_lambda_ric
を実行してから、CMD
で app.rb
に記述されている lambda_handler
を実行します。
FROM redmine:4.2.3 # lambdaでコンテナを実行するために必要なGemをインストール RUN gem install aws_lambda_ric ... # lambdaでは/tmp以外でファイルの書き込みができないため、ログの出力先の変更必要。 # 以下はRedmine独自の書き方なので、通常のRailsの場合は書き方が違います。 RUN echo 'config.logger = Logger.new("/tmp/production.log")' > config/additional_environment.rb ... # 注)今回はサンプルのためコンテナイメージにDBを含めています。 RUN rails db:create RUN rails db:migrate # 実行準備の処理 ENTRYPOINT ["/usr/local/bundle/bin/aws_lambda_ric"] # ファイル名とメソッド名を記述 CMD ["app.lambda_handler"]
hello_world/app.rb
require 'json' require 'open3' def lambda_handler(event:, context:) # rails db:migrate:status を実行してMigrationの状態を確認 command = %*rails db:migrate:status* p command res = Open3.capture3(command) p res { statusCode: 200, body: { message: "success!", }.to_json } end
以上、設定が終わりましたら、ローカルで実行してみます。
sam build
を実行してローカルでイメージのビルドします。
$ sam build # コンテナイメージのビルドが実行されます(省略)
ビルドが無事に終わりましたら、sam local invoke
を実行してローカルでの動作確認します。
$ sam local invoke Invoking Container created from helloworldfunction:rails-v1 Building image................. Skip pulling image and use local one: helloworldfunction:rapid-1.37.0-x86_64. START RequestId: 6cd1485f-4e7a-4a95-b184-b7cf1387f182 Version: $LATEST Skipped bootstraping TelemetryLog Executing 'app.lambda_handler' in function directory '/usr/src/redmine' "rails db:migrate:status" ["database: /usr/src/redmine/sqlite/redmine.db Status Migration ID Migration Name -------------------------------------------------- up 001 Setup up 002 Issue move up 003 Issue add note up 004 Export pdf ...(省略) up 20180923091603 Change sqlite booleans default up 20190315094151 Change custom values value limit up 20190315102101 Add trackers description up 20190510070108 Add unique id to import items up 20190620135549 Change roles name limit up 20200826153401 Add twofa scheme to user up 20200826153402 Add totp to user", "", #<Process::Status: pid 16 exit 0>] {"statusCode":200,"body":"{\"message\":\"success!\"}"}END RequestId: 6cd1485f-4e7a-4a95-b184-b7cf1387f182 REPORT RequestId: 6cd1485f-4e7a-4a95-b184-b7cf1387f182 Init Duration: 1.88 ms Duration: 4743.01 ms Billed Duration: 4744 ms Memory Size: 512 MB Max Memory Used: 512 MB
上記のように rails db:migrate:status
の出力されれば、設定完了です。
続いて、sam depelop
を実行して、実際に AWS にデプロイして動作確認をします。
$ sam deploy --guided Configuring SAM deploy ====================== Looking for config file [samconfig.toml] : Not found Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: rails-sample AWS Region [ap-northeast-1]: ap-northeast-1 #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: Save arguments to configuration file [Y/n]: SAM configuration file [samconfig.toml]: SAM configuration environment [default]: Looking for resources needed for deployment: Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-1dix87p43yhyp A different default S3 bucket can be set in samconfig.toml Image repositories: Not found. #Managed repositories will be deleted when their functions are removed from the template and deployed Create managed ECR repositories for all functions? [Y/n]: Y Saved arguments to config file Running 'sam deploy' for future deployments will use the parameters saved above. The above parameters can be changed by modifying samconfig.toml Learn more about samconfig.toml syntax at https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html d55f284a5036: Pushed ... # イメージのプッシュ(省略) ... helloworldfunction-7b5365a72273-rails-v1: digest: sha256:2386cb0e3828b8f3a0f3d97a33d02acc9ddd3f88969889224430c8649a799df2 size: 4078 Deploying with following values =============================== Stack name : rails-sample Region : ap-northeast-1 Confirm changeset : False Disable rollback : False Deployment image repository : { "HelloWorldFunction": "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/railssample4b62256f/helloworldfunction19d43fc4repo" } Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1dix87p43yhyp Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {} Signing Profiles : {} Initiating deployment ===================== Uploading to rails-sample/08aa59625af12cd81a3f45d9157a1969.template 972 / 972 (100.00%) Waiting for changeset to be created.. ... # cloudformationを利用したデプロイの実行ログが表示されます。(省略) ... CloudFormation outputs from deployed stack ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Outputs ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Key HelloWorldFunctionIamRole Description Implicit IAM Role created for Hello World function Value arn:aws:iam::xxxxxxxxxxxx:role/rails-sample-HelloWorldFunctionRole-1HJZLKA9J0ZKD Key HelloWorldFunction Description Hello World Lambda Function ARN Value arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:rails-sample-HelloWorldFunction-M9azD5kDY5Cl ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Successfully created/updated stack - rails-sample in ap-northeast-1
上記のように Successfully created/updated stack 出力されれば、OK です。
ポイントとしては、初回のみ、以下のように設定の確認がありますが、Stack Name [sam-app]: rails-sample
以外はデフォルトの値で実行できると思います。
Looking for config file [samconfig.toml] : Not found Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: rails-sample AWS Region [ap-northeast-1]: ap-northeast-1 #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: Save arguments to configuration file [Y/n]: SAM configuration file [samconfig.toml]: SAM configuration environment [default]: Looking for resources needed for deployment: Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-1dix87p43yhyp A different default S3 bucket can be set in samconfig.toml Image repositories: Not found. #Managed repositories will be deleted when their functions are removed from the template and deployed Create managed ECR repositories for all functions? [Y/n]: Y Saved arguments to config file Running 'sam deploy' for future deployments will use the parameters saved above. The above parameters can be changed by modifying samconfig.toml Learn more about samconfig.toml syntax at https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
ちなみに 2 回目以降は
$ sam build $ sam deploy
の順で実行すればデプロイされます。
最後に AWS にログインして lambda を実行してみます。
デプロイされている Lambda でテストを実行します。
今回は event を利用していないので、デフォルトのままで OK です。
数十秒待つと実行結果が出力されます。
rails db:migrate:status
の出力結果が確認できれば、今回の作業は無事に完了です。
今回紹介した新機能を利用すれば、複数の DB の対して同時に rails db:migration を実行することも簡単(短時間)です。 弊社でも DB の migration を実行する際にはこちらで紹介した技術を利用することで短時間で、大量の DB に対してアップデートを行うことが可能になりました。
実際には AWS CodePipeline や StepFunctions なども利用しており、アーキテクチャは少し複雑になりますが、それでもスクリプトを書いて EC2 などを利用して実行するより簡潔かつ安全に実行できるのではと思っております(EC2の場合Pipelineなどに組み込みにくい)。 また機会がありましたらそのアーキテクチャの紹介もしたいと思います。
注 1)Lambda から RDS へアクセスする際は、AWS RDS Proxy の利用が推奨されています。
注 2)Lambda を複数同時実行し、migration を実行する際は DB のリソースが枯渇する可能性が高いので、それぞれの用途に合わせて検証は必要です。
![]() |
Lambda ruby 2.7を利用してRDS(postgresql)と通信をできるようにする方法の紹介。 |
![]() |
最近使っているスマートデバイスを紹介。Amazon Echoの複数台利用で便利に。 |
![]() |
My Redmineのお客様から作業時間一覧についてお問い合わせをいただきRedmineを改善。 |
![]() |
統計分析の学びとしてR言語を使い始めました。R言語は利用までのコストが低く、情報も多いのでお勧めです。 |
![]() |
「RedMica Bridge」はシンプルなUIで簡単にチケットに入力でき、複数のRedmineのチケットを表示することができます。 |
![]() |
社員研修に伴うサポート体制変更・休業のお知らせ(5/20〜23) 社員研修に伴い、5月20日〜23日はサポート体制の変更および休業とさせていただきます。 |
![]() |
オープンソースカンファレンス2025 Nagoyaに弊社代表の前田が登壇(ブース出展あり) オープンソースカンファレンス(OSC)2025 Nagoyaに弊社代表の前田が登壇。『Redmineの意外と知らない便利な機能(Redmine 6.0 対応版)』をテーマに発表します。 |
![]() |
エンタープライズプラン向け「優先サポート」を開始 My Redmineでは、エンタープライズプランをご契約のお客様向けにサポート対応を優先的に行う「優先サポート(プライオリティサポート)」を開始いたしました。 |
![]() |
プロジェクト管理ツール「RedMica」バージョン 3.1.0をリリース Redmine互換のオープンソースソフトウェア ファーエンドテクノロジー株式会社は、2024年11月19日(日本時間)、Redmine互換のプロジェクト管理ソフトウェア「RedMica 3.1.0」をリリースしました。 |
![]() |
Redmineの最新情報をメールでお知らせする「Redmine News」配信中 新バージョンやセキュリティ修正のリリース情報、そのほか最新情報を迅速にお届け |