diff --git a/Dockerfile b/Dockerfile index 432cc5e..7eb42cd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,9 @@ RUN echo "git_ref: $git_ref" COPY . /var/task/datadog-lambda-rb WORKDIR /var/task/datadog-lambda-rb RUN apt-get update -RUN apt-get install -y gcc zip binutils +# `libffi-dev` + `make` are needed to compile the `ffi` gem from source +# below — see the rebuild step after the datadog gem install. +RUN apt-get install -y gcc zip binutils make libffi-dev pkg-config # Install this gem RUN gem build datadog-lambda @@ -26,6 +28,29 @@ RUN set -eux; \ gem install ./datadog-*.gem --install-dir "/opt/ruby/gems/$runtime"; \ fi +# Force `ffi` to be (re)built from source in this per-runtime builder so +# the resulting `ffi_c.so` matches the target Lambda runtime's Ruby ABI +# exactly. The precompiled `ffi-x.y.z-x86_64-linux-gnu` gem shipped via +# rubygems ships ABI-specific subdirs (`lib/3.3/ffi_c.so`, +# `lib/3.4/ffi_c.so`, …) and `ffi 1.17` does NOT include a Ruby 3.2 +# subdir. Without this step, dd-trace-rb 2.30's AppSec component (which +# `require`s libddwaf → ffi → ffi_c) crashes the function at boot on +# Ruby 3.2 when `DD_APPSEC_ENABLED=true`: +# +# Init: cannot load such file -- ffi_c +# +# Confirmed via a single-lambda sandbox repro on 2026-05-15 +# (datadog-lambda-rb v3.28.0, Datadog-Ruby3-2:28 + DD_APPSEC_ENABLED=true). +# Same combo on Ruby 3.4 / 4.0 works because the precompiled package does +# bundle binaries for their ABIs, but compiling from source here is a +# permanent fix that's defensive against future `ffi` releases dropping +# additional Ruby ABIs from the precompiled bundle. +RUN set -eux; \ + gem uninstall ffi --all --ignore-dependencies --executables --force \ + --install-dir "/opt/ruby/gems/$runtime" || true; \ + gem install ffi --platform=ruby \ + --install-dir "/opt/ruby/gems/$runtime" + WORKDIR /opt # Remove native extension debase-ruby_core_source (25MB) runtimes below Ruby 2.6 RUN rm -rf ./ruby/gems/$runtime/gems/debase-ruby_core_source*/