customink/mysql2-lambda

Ruby 2.7.5

redvex opened this issue · 6 comments

The gem doesn't seem to work on ruby 2.7.5

Bundle installs all the gems, but when I try to require the gem, I get this error:

irb(main):002:0> require 'mysql2'
Traceback (most recent call last):
       10: from /var/lang/bin/irb:23:in `<main>'
        9: from /var/lang/bin/irb:23:in `load'
        8: from /var/lang/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
        7: from (irb):2
        6: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:149:in `require'
        5: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:160:in `rescue in require'
        4: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:160:in `require'
        3: from /var/task/vendor/bundle/gems/mysql2-lambda-0.5.3.1/lib/mysql2.rb:36:in `<top (required)>'
        2: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
        1: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
LoadError (/var/task/vendor/bundle/gems/mysql2-lambda-0.5.3.1/lib/mysql2/mysql2.so: cannot open shared object file: No such file or directory - /var/task/vendor/bundle/gems/mysql2-lambda-0.5.3.1/lib/mysql2/mysql2.so)

It worked with ruby 2.7.4, but AWS updated the base image with ruby 2.7.5

Here is my Dockerfile:

FROM public.ecr.aws/lambda/ruby:2.7

# Copy dependency management file
COPY lambda/Gemfile ${LAMBDA_TASK_ROOT}

# Install dependencies under LAMBDA_TASK_ROOT
ENV GEM_HOME=${LAMBDA_TASK_ROOT}/vendor/bundle
RUN bundle install
# Copy function code
COPY lambda ${LAMBDA_TASK_ROOT}

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "lambda_function.LambdaFunction::Handler.process" ]

The file is there

sh-4.2# ls -l /var/task/vendor/bundle/gems/mysql2-lambda-0.5.3.1/lib/mysql2/mysql2.so
-rwxr-xr-x 1 root root 5363112 Dec  1 15:08 /var/task/vendor/bundle/gems/mysql2-lambda-0.5.3.1/lib/mysql2/mysql2.so

but it doesn't seem to be a dynamic exec

sh-4.2# ldd /var/task/vendor/bundle/gems/mysql2-lambda-0.5.3.1/lib/mysql2/mysql2.so
        not a dynamic executable

I just rebuilt the gem with the latest images and published v0.5.3.2. Can you try that out?

unfortunately still same issue:

irb(main):001:0> require 'mysql2'
Traceback (most recent call last):
       10: from /var/lang/bin/irb:23:in `<main>'
        9: from /var/lang/bin/irb:23:in `load'
        8: from /var/lang/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
        7: from (irb):1
        6: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:149:in `require'
        5: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:160:in `rescue in require'
        4: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:160:in `require'
        3: from /var/task/vendor/bundle/gems/mysql2-lambda-0.5.3.2/lib/mysql2.rb:36:in `<top (required)>'
        2: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
        1: from /var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
LoadError (/var/task/vendor/bundle/gems/mysql2-lambda-0.5.3.2/lib/mysql2/mysql2.so: cannot open shared object file: No such file or directory - /var/task/vendor/bundle/gems/mysql2-lambda-0.5.3.2/lib/mysql2/mysql2.so)

It seems a arch-related issue!
Forcing the platform to linux/amd64 works:

Dockerfile:

FROM --platform=linux/amd64 public.ecr.aws/lambda/ruby:2.7

# Copy dependency management file
COPY lambda/Gemfile ${LAMBDA_TASK_ROOT}

# Install dependencies under LAMBDA_TASK_ROOT
ENV GEM_HOME=${LAMBDA_TASK_ROOT}/vendor/bundle
RUN bundle install
# Copy function code
COPY lambda ${LAMBDA_TASK_ROOT}

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "lambda_function.LambdaFunction::Handler.process" ]

Sh:

sh-4.2# arch
x86_64
sh-4.2# irb
irb(main):001:0> require 'mysql2'
=> true
irb(main):002:0> 

Oh! So your image is amd64? I've never published a gem with multiple architecture needs before. Do you have thoughts on that? Should I publish a mysql2-lambda-amd64?

Actually, to make it work I had to force my image to be based on amd64 version. On my M1, by default it uses the arm64 base image. Considering that using arm64 is an option on Lambda, would be great to have the option.

It could. I'd like to consider this project deprecated given we now have Lambda Containers and can easily install the needed development/build and/or runtime dependencies as needed in each of our containers. I recently provided an example in the new Lamby Cookiecutter work which is based on Ruby 3.1 official Debian images. Details here:

rails-lambda/lamby-cookiecutter#21