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/
以下でないと書き込み権限がないのでそこだけ注意が必要です.
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は難しいことはなくリポジトリを作成をしてリポジトリ画面のプッシュコマンドを表示に丁寧に書かれているので迷うことはないと思います.
- 認証トークンを取得し、レジストリに対して Docker クライアントを認証します。AWS CLI を使用します.
aws ecr get-login-password --region REGION | docker login --username AWS --password-
stdin XXX.dkr.ecr.XXX.amazonaws.com
- 以下のコマンドを使用して、Docker イメージを構築します.
docker build -t ffmpeg-lambda .
- 構築が完了したら、このリポジトリにイメージをプッシュできるように、イメージにタグを付けます.
docker tag ffmpeg-lambda:latest XXX.dkr.ecr.XXX.amazonaws.com/ffmpeg-lambda:latest
- 以下のコマンドを実行して、新しく作成した AWS リポジトリにこのイメージをプッシュします.
docker push XXX.dkr.ecr.XXX.amazonaws.com/ffmpeg-lambda:latest
Lambda関数の作成
Lambdaを作っていきましょう.
コンテナイメージを選択して先ほど作成したコンテナイメージを指定してすれば作成は完了です.
このまま実行するとデフォルトのタイムアウト設定が3秒になっているため失敗していまいます.
基本設定からタイムアウトの時間を伸ばす必要がありました.
S3に動画をアップロードして gif ができていれば完成です!
感想
感想としてはすごく簡単に実装が完了しました.
また従来のzipパッケージのアップロードが最大250MBと比べてイメージサイズが10GBまで許可されるようになったりと今までより柔軟になりました.
yumなどでインストールができるようになるので利用可能なシーンの幅が広がったように思いました.
最後に
Increments × cyma (Ateam Inc.) Advent Calendar 2020 の22日目は、
株式会社エイチームの @o93 が担当します!