I made a Ruby container image and moved the Lambda function

@Kiitan of Increments Inc. will be in charge of the 21st day of Increments × cyma (Ateam Inc.) Advent Calendar 2020.

Introduction

Amazon Web Services (AWS) announced AWS Lambda container support at the annual event "AWS re: Invent 2020" that is being held online. In short, the image pushed to the ECR repository can now be used in Lambda functions. So I immediately touched it.

What to make

When a video is uploaded to S3, we will create a gif and create a Lambda function that will upload it to S3.

Implementation

The file structure this time is as follows.

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

For app.rb, S3 just gets the video from, converts it to a gif, and uploads it again. When saving a file by Lambda's method, you need to be careful because you do not have write permission unless it is under 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}"

      #Get the video uploaded from S3/tmp/Save to
      movie_file = s3_client.get_object(:bucket => input_bucket, :key => input_key).body.read
      File.write(file_path, movie_file)

      #Load video with ffmpeg and convert it to gif
      movie = FFMPEG::Movie.new(file_path)
      #Cut the start 6 seconds and convert it to gif
      options = {frame_rate: '10', duration: '00:00:6.000'}
      movie.transcode("#{file_path}.gif", options)

      #S3 gif/Upload the gif created below
      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'

Next, regarding Dockerfile, not all base images can be used, and the Lambda Runtime API for Lambda must be implemented.

<!-Container for Lambda ruby-> in ECR Public gallery

This time, we will use amazon/aws-lambda-ruby: 2.7 as a base image. There is nothing to be careful about other than the base image, it is a very simple Dockerfile that just downloads ffmpeg and installs gem.

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"]

Push to ECR

Pushing to ECR is not difficult, and you will not get lost because the repository is created and the push command on the repository screen is carefully written on the display.

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

  1. Obtain an authentication token and authenticate the Docker client to the registry. Use the AWS CLI.
aws ecr get-login-password --region REGION | docker login --username AWS --password-
stdin XXX.dkr.ecr.XXX.amazonaws.com
  1. Build a Docker image using the following command.
docker build -t ffmpeg-lambda .
  1. Once the build is complete, tag the image so that you can push it to this repository.
docker tag ffmpeg-lambda:latest XXX.dkr.ecr.XXX.amazonaws.com/ffmpeg-lambda:latest
  1. Run the following command to push this image to your newly created AWS repository.
docker push XXX.dkr.ecr.XXX.amazonaws.com/ffmpeg-lambda:latest

Creating a Lambda function

Let's make Lambda. Select the container image and specify the container image you created earlier to complete the creation.

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

After that, create and set the trigger as usual スクリーンショット 2020-12-14 3.37.05.png

If you execute it as it is, it fails because the default timeout setting is 3 seconds. It was necessary to extend the timeout time from the basic settings.

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

If you upload the video to S3 and have a gif, you're done!

Impressions

As for the impression, the implementation was completed very easily.

In addition, uploading of the conventional zip package is now allowed up to 10GB of image size compared to the maximum of 250MB, making it more flexible than before. I think that the range of available scenes has expanded because it can be installed with yum etc.

Finally

The 22nd day of Increments x cyma (Ateam Inc.) Advent Calendar 2020 @ O93 of Ateam Co., Ltd. is in charge!

Recommended Posts

I made a Ruby container image and moved the Lambda function
[Ruby] I made a crawler with anemone and nokogiri.
I tried JAX-RS and made a note of the procedure
Ruby: I made a FizzBuzz program!
I made a simple recommendation function.
I made a reply function for the Rails Tutorial extension (Part 1)
I made a reply function for the Rails Tutorial extension (Part 5):
[Ruby] I made a simple Ping client
I made a risky die with Ruby
I wrote a Lambda function in Java and deployed it with SAM
I made a Docker container to run Maven
I made a Ruby extension library in C
[Rails] I made a draft function using enum
I made a portfolio with Ruby On Rails
I made a Docker image of SDAPS for Japanese
[Ruby] I thought about the difference between each_with_index and each.with_index
I made a check tool for the release module
[AWS Lambda] Resize the image saved in S3 and save it in another S3 (using Ruby)
I made a Restful server and client in Spring.
I want to add a delete function to the comment function
left4dead2 I made a Docker image for the server and tried running it on GCE # 3 (I had a hard time building the server)
I made a reply function for the Rails Tutorial extension (Part 4): A function that makes the user unique
I changed the Ruby version and now I can't bundle install
I want to call a method and count the number
I want to make a function with kotlin and java!
A note about the seed function of Ruby on Rails
The nth and n + 1st characters of a Ruby string
I made a chat app.
A story that a Ruby beginner made and released a LINE BOT that tells the train time in 2 months
[Learning record] I got the current time in Ruby and output a different greeting for each time.
Create a private repository in Amazon ECR and push/pull the image
I created a Docker image of a container for learning OpenAI Gym
[Ruby] Relationship between parent class and child class. The relationship between a class and an instance.
[Ruby] Difference between symbol variables and character string variables. About the difference between [: a] and ['a'].
I tried to implement the image preview function with Rails / jQuery
I recently made a js app in the rumored Dart language
I tried using the cache function of Application Container Cloud Service
I made a gem to post the text of org-mode to qiita
I took a look at the resources of Azure Container Instance
I tried deploying a Docker container on Lambda with Serverless Framework
[Illustration] Finding the sum of coins with a recursive function [Ruby]
I made a tool to output the difference of CSV file
(Ruby on Rails6) Create a function to edit the posted content
I want to download a file on the Internet using Ruby and save it locally (with caution)
I made a shopify app @java
I made a GUI with Swing
I made a matching app (Android app)
I made a package.xml generation tool.
[Android] I made a pedometer app.
I was a little addicted to running old Ruby environment and old Rails
[Ruby] I want to extract only the value of the hash and only the key
I made a virtual currency arbitrage bot and tried to make money
I tried running the route search engine (OSRM) easily with a container
I thought about the best way to create a ValueObject in Ruby
I made a class that can use JUMAN and KNP from Java
I made a reply function for Rails Tutorial extension (Part 2): Change model
After verifying the Monty Hall problem with Ruby, a story that I could understand well and did not understand well
[Ruby] I want to make an array from a character string with the split method. And vice versa.