5
4

More than 3 years have passed since last update.

Lambda関数をRuby コンテナイメージを作って動かしてみた

Last updated at Posted at 2020-12-20

Increments × cyma (Ateam Inc.) Advent Calendar 2020 の21日目は、Increments株式会社の @kiitan が担当します

はじめに

Amazon Web Services(AWS)は、オンラインで開催中の年次イベント「AWS re:Invent 2020」で、AWS Lambdaのコンテナサポートを発表しました。要するにECRリポジトリにPushしたイメージをLambda関数で使うことができるようになったよってことでした。そこで早速触ってみました.

作るもの

S3に動画をアップロードされると gif 作成してS3にアップロードしてくれるLambda関数を作っていきます.

実装

今回のファイル構成は以下のようになります.

├── Dockerfile
├── Gemfile
├── Gemfile.lock
└── app.rb

app.rb はS3がから動画を取得してgifに変換してまたアップロードしてあげるだけ.
Lambdaのお作法でファイルを保存する場合は tmp/ 以下でないと書き込み権限がないのでそこだけ注意が必要です.

app.rb
require 'aws-sdk-s3'
require 'streamio-ffmpeg'

module LambdaFunction
  class Handler
    def self.process(event:, context:)
      s3_client = Aws::S3::Client.new(
                           :region => ENV['REGION'],
                           :access_key_id => ENV['ACCESS_KEY'],
                           :secret_access_key => ENV['SECRET_ACCESS_KEY']
                          )
      input_bucket = event['Records'][0]['s3']['bucket']['name']
      input_key = event['Records'][0]['s3']['object']['key']
      file_name = input_key.split("/").last
      file_path = "/tmp/#{file_name}"

      # S3からアップロードされた動画を取得し /tmp/ に保存する
      movie_file = s3_client.get_object(:bucket => input_bucket, :key => input_key).body.read
      File.write(file_path, movie_file)

      # ffmpeg で動画を読み込み gif に変換する
      movie = FFMPEG::Movie.new(file_path)
      # 開始6秒間を切り取って gif に変換する
      options = {frame_rate: '10', duration: '00:00:6.000'}
      movie.transcode("#{file_path}.gif", options)

      # S3 の gif/ 以下に作成した gif をアップロードする
      movie_object = s3_client.put_object({ 
        :bucket => input_bucket,
        :key => "gif/#{file_name}.gif",
        :body => File.new("#{file_path}.gif"),
      })
    end
  end
end
source 'https://rubygems.org'

ruby '2.7.2'

gem 'streamio-ffmpeg'
gem 'aws-sdk'

次に Dockerfile に関してですが,ベースイメージはどんなものでも利用できる訳ではなくLambda用のLambda Runtime APIが実装されている必要があります.

今回は amazon/aws-lambda-ruby:2.7 をベーズイメージとして利用していきます.
ベースイメージ以外は気をつけることは特になくffmpeg をダンロード配置してgem をインストールするだけのいたってシンプルなDockerfileになります.

FROM amazon/aws-lambda-ruby:2.7

RUN yum -y install wget tar xz xz-devel
RUN wget https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xz \
      && tar Jxvf ./ffmpeg-git-amd64-static.tar.xz \
      && cp ./ffmpeg*amd64-static/ffmpeg /usr/local/bin/ \
      && cp ./ffmpeg*amd64-static/ffprobe /usr/local/bin/ 
COPY Gemfile Gemfile.lock ./
RUN bundle install --path vendor/bundle
COPY app.rb ./

CMD ["app.LambdaFunction::Handler.process"]

ECRへpush

ECRへpushは難しいことはなくリポジトリを作成をしてリポジトリ画面のプッシュコマンドを表示に丁寧に書かれているので迷うことはないと思います.

スクリーンショット 2020-12-18 3.12.25.png

  1. 認証トークンを取得し、レジストリに対して Docker クライアントを認証します。AWS CLI を使用します.
aws ecr get-login-password --region REGION | docker login --username AWS --password-
stdin XXX.dkr.ecr.XXX.amazonaws.com
  1. 以下のコマンドを使用して、Docker イメージを構築します.
docker build -t ffmpeg-lambda .
  1. 構築が完了したら、このリポジトリにイメージをプッシュできるように、イメージにタグを付けます.
docker tag ffmpeg-lambda:latest XXX.dkr.ecr.XXX.amazonaws.com/ffmpeg-lambda:latest
  1. 以下のコマンドを実行して、新しく作成した AWS リポジトリにこのイメージをプッシュします.
docker push XXX.dkr.ecr.XXX.amazonaws.com/ffmpeg-lambda:latest

Lambda関数の作成

Lambdaを作っていきましょう.
コンテナイメージを選択して先ほど作成したコンテナイメージを指定してすれば作成は完了です.

スクリーンショット 2020-12-14 3.08.08.png

あとはいつも通りにトリガーを作成設定する
スクリーンショット 2020-12-14 3.37.05.png

このまま実行するとデフォルトのタイムアウト設定が3秒になっているため失敗していまいます.
基本設定からタイムアウトの時間を伸ばす必要がありました.

スクリーンショット 2020-12-18 3.36.29.png

S3に動画をアップロードして gif ができていれば完成です!

感想

感想としてはすごく簡単に実装が完了しました.

また従来のzipパッケージのアップロードが最大250MBと比べてイメージサイズが10GBまで許可されるようになったりと今までより柔軟になりました.
yumなどでインストールができるようになるので利用可能なシーンの幅が広がったように思いました.

最後に

Increments × cyma (Ateam Inc.) Advent Calendar 2020 の22日目は、
株式会社エイチームの @o93 が担当します!

5
4
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
5
4