LoginSignup
0
0

More than 1 year has passed since last update.

AWS SAM CLIを使わずにLambda+Ruby2.7でNokogiriなどのGemを使う方法

Posted at

概要

Lambda+Rubyでgem(Nokogiri)を使おうと思ったところ

cannot load such file -- nokogiri/nokogiri

というエラーになってしまい、使えなかったので使えるようにした話

前段

調べると、割とAWS SAM CLIを使った方法が出てきて手順自体は簡単なのですが何してるかわからん...というふうになってしまったので、今回はそちらを使わない方法にしたいと思います。

準備するもの

  • Lambdaのソースファイル
  • Docker環境

手順

Lambdaで動かすソースコードの準備

自分の使っているコードが有る場合は

この記事を参考にエクスポートしてもらうと良いかと。

自分は今回このようなコードを準備しました。
Gemfile

source 'https://rubygems.org'

gem 'nokogiri'

lambda_funcrion.rb

require 'json'
require 'nokogiri'
require 'kconv'
require 'net/http'
require 'uri'

def lambda_handler(event:, context:)

    area = URI.encode_www_form_component('横浜')
    keyword = URI.encode_www_form_component('居酒屋')
    
    uri = URI.parse("https://r.gnavi.co.jp/area/jp/rs/?fwp=#{area}&date=&fw=#{keyword}")
    request = Net::HTTP::Get.new(uri)
    request["Authority"] = "r.gnavi.co.jp"
    request["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
    request["Accept-Language"] = "ja"
    request["Cache-Control"] = "max-age=0"
    request["Cookie"] = "_td_global=2c7201bb-65d9-447f-8871-5c8aef70e6f0; _ra=1664900409701|e581f62a-e16f-4c02-97dc-b7ab203924e6; GU=e9f8c8528b624ea8cb1a55aadf705bd0; gt=GT139faa476002ac1e4ae520fpfeoIzpEqTDWQ1Rwc2xzV; ds=622474de466075942cc80e90a606c14bc6c474c7b09327535e48d587017aa4c0; gUser=03139faa476003ac1e4ae520L_I2dpFCb1q8eMMN-5-LmU; gcom=%7B%22login_type%22%3A1%2C%22guser_type%22%3A0%7D; _gid=GA1.3.151665219.1669743686; __gads=ID=61224817bcdcc5e2:T=1669743685:S=ALNI_MYQItLoO9f62eC3t0aHssBPge-pXQ; __gpi=UID=00000b86e8eecc21:T=1669743685:RT=1669743685:S=ALNI_MZ324J7fmISVdaU-A1IuoqdhZBTIQ; _ts_yjad=1669743686386; _fbp=fb.2.1669743686439.1159228644; _gcl_au=1.1.1560200380.1669743686; __pp_uid=INDH6tuKhtkFKURk66AXkbVTWOoJTybu; __lt__cid=c5331b8a-2798-4df1-9a8c-afb6b1af0c3c; __lt__sid=ab800c27-56441560; _dctagfq=1318:1670338799.0.0|1319:1670338799.0.0|1320:1670338799.0.0|1321:1670338799.0.0|1536:1670338799.0.0|1841:1670338799.0.0|1856:1670338799.0.0|1871:1670338799.0.0|1886:1670338799.0.0|1901:1670338799.0.0|1916:1670338799.0.0|1931:1670338799.0.0; ___o2u_o2id=0793b44a-526d-4f6f-bbfb-c923eb5be40f; rtosrch=gg7t002%3Dhttps%253A%252F%252Fr.gnavi.co.jp%252Farea%252Fjp%252Frs%252F%253Ffwp%253D%2525E6%2525A8%2525AA%2525E6%2525B5%25259C%2526date%253D%2526fw%253D%2525E3%252581%25259F%2525E3%252581%252593%2525E7%252584%2525BC%2525E3%252581%25258D%26a567203%3Dhttps%253A%252F%252Fr.gnavi.co.jp%252Farea%252Fjp%252Frs%252F%253Ffw%253D%2525E5%2525B1%252585%2525E9%252585%252592%2525E5%2525B1%25258B%2526fwp%253D%2525E6%2525A8%2525AA%2525E6%2525B5%25259C; GHistory=a567203%3A110%3A1669744542%2Cgg7t002%3A110%3A1669744522; ghistory_reserve=a567203%3A1669744542%2Cgg7t002%3A1669744522; __cribnotes_prm=__t_1669744547013_%7B%22uuid%22%3A%227a38921c-4d2e-4d30-bcb9-80d0686da7f0%22%7D; cto_bundle=sGp-Ll9kUDVaaHJYMHN3SkFtYyUyQkFmUTh2QWdka0pTQ0xqWlhHVFpETzB3ckh4dG1ya0J4NTB1Y0Z1V09mOUtMRDJWRlBKbDNSU2FTMWFDRXgyOFU4Q0l6UzAzYWFoWE9TMVd0WmVqOFZVcjBmQ3JHVHJyNkFodzhVcDlKTGdRYTBIWXNEdHdET3RzeENSc0Q0eDRGdUlwJTJGS3pWJTJGaXk1QW9sajk1ZUhJRHNaelpaYSUyRllHR0klMkZlNnhWWXIlMkJYTXB3eU00eUw; s_sess=%20sc_oncook%3D%3B%20sc_prop1%3Dr%3B%20cpnt_referer%3D%3B; _dc_gtm_UA-43329175-1=1; _td=639fb236-c732-4fb7-b246-0a6ed66c2a87; _ga_L9BHK8C28C=GS1.1.1669743685.1.1.1669744820.51.0.0; _ga=GA1.1.111137152.1669743686"
    request["Sec-Ch-Ua"] = "\"Google Chrome\";v=\"105\", \"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"105\""
    request["Sec-Ch-Ua-Mobile"] = "?0"
    request["Sec-Ch-Ua-Platform"] = "\"macOS\""
    request["Sec-Fetch-Dest"] = "document"
    request["Sec-Fetch-Mode"] = "navigate"
    request["Sec-Fetch-Site"] = "same-origin"
    request["Sec-Fetch-User"] = "?1"
    request["Upgrade-Insecure-Requests"] = "1"
    request["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"
    
    req_options = {
      use_ssl: uri.scheme == "https",
    }
    
    response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
      http.request(request)
    end
    
    doc = Nokogiri::HTML.parse(response.body.toutf8, nil, 'utf-8')
    result = doc.css('.style_restaurantNameWrap__wvXSR').map do |target|
      target.text
    end
  
  { statusCode: 200, body: JSON.generate(result) }
end

中身の細かい話が知りたければ

これとか読んでください。
1文で要約すると「ぐるなびのサイトを検索して情報を店舗名を取得するコード」です。
これをLambdaで動かします。

Dockerfileの準備

次にDockerfileを準備します。
Lambdaのソースファイルが有るディレクトリにDockerfileを作成します。
そして下記のような記述をします。

FROM lambci/lambda:build-ruby2.7

CMD "/bin/bash"

そもそもなんでローカルのbundle installをしただけでは動かないのかという話なのですが、nokogiriなどのgemは環境ごとのネイティブなライブラリを参照しており、手元の環境とLambda環境ではそれが異なるために起きてしまっているんですね。
そのため、Lambda用のDocker環境を準備してそこでビルドしてあげたものをアップすればいいじゃんという話なのです!

Dockerビルド

下記のコマンドでDockerビルドを行います。

docker build -t lambda-ruby2.7 .

bundle install

次に下記のコマンドでDocker環境の中に入り

docker run --rm -it -v $PWD:/var/task -w /var/task lambda-ruby2.7

bundle installを行います

bundle install --path vendor/bundle --clean

終わったら

exit

で抜けます。

ソースファイルをZIP化

そしたらbundle installしたライブラリごとzip化します。

zip -q -r deploy.zip .

Lambdaにアップロード

スクリーンショット 2022-12-17 15.20.38.png
スクリーンショット 2022-12-17 15.20.44.png

最後にLambdaの環境にアップロードして、完了!!

0
0
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
0
0