Skip to content

bundler: git gems missing from runtime image in multi-stage container builds #1630

Description

@romanblanco

Describe the issue

When a Gemfile declares a git dependency (via github:, git:, or branch:/ref: options), Hermeto configures bundler to use the pre-fetched local clone via BUNDLE_LOCAL.* config entries.

This causes bundler to use the gem in-place from Hermeto's output directory rather than installing it into BUNDLE_PATH.
In a multi-stage container build, the runtime image ends up missing those gems, causing load errors at startup.

This is a problem for repositories depending on a fork or an unreleased branch:

# Gemfile                                                                                                                                                                                                         
source 'https://rubygems.org'                                                                                                                                                                                     
gem 'json-schema', github: '3scale/json-schema'                                                                                                                                                                   

After hermeto fetch-deps, the generated bundler config contains:

BUNDLE_DISABLE_LOCAL_BRANCH_CHECK: "true"                                                                                                                                                                         
BUNDLE_DISABLE_LOCAL_REVISION_CHECK: "true"                                                                                                                                                                       
BUNDLE_LOCAL.JSON___SCHEMA: "${output_dir}/deps/bundler/json-schema-26487618a684" 
#                              ^^^ points into Hermeto's output directory                                                                                                                                

With BUNDLE_LOCAL.* active, bundler reads the gem in-place from Hermeto's output directory and never copies it into BUNDLE_PATH:

def requires_checkout?
    allow_git_ops? && !local? && !locked_revision_checked_out?
    #                 ^^^
    #                 false when BUNDLE_LOCAL.* is set -> checkout never runs
end

In a multi-stage build the build stage can reach the output directory, but the runtime stage copies only .bundle/ — so the gem disappears:

FROM ruby:3.3 AS build
COPY . .
RUN bundle install   # hermeto supplies BUNDLE_APP_CONFIG

FROM ruby:3.3
COPY --from=build .bundle/ .bundle/
# json-schema is missing here → LoadError at startup

Version

  • I have reproduced this issue on the latest version from the main branch

Steps to reproduce

# /tmp/myapp/Gemfile
source 'https://rubygems.org'
gem 'json-schema', github: '3scale/json-schema'
bundle lock # generates Gemfile.lock with a GIT section
hermeto fetch-deps --source /tmp/myapp --output /tmp/hermeto-output bundler
# Inspect the generated config
grep -A1 BUNDLE_LOCAL /tmp/hermeto-output/bundler/config_override/config
# Simulate hermetic bundle install
BUNDLE_APP_CONFIG=/tmp/hermeto-output/bundler/config_override BUNDLE_PATH=/tmp/mybundle bundle install --local
# Gem is not in BUNDLE_PATH
ls /tmp/mybundle/ruby/*/bundler/gems/

Environment

  • OS: Fedora Linux 43
  • Deployment: localhost
  • Ruby: 3.3.10
  • Bundler: 2.5.22
  • git: 2.54.0

How does this issue affect you, or how did you find it?

Since merging RedHatInsights/compliance-backend#2753, our service is not starting properly.

We're using gem from a forked repository: https://github.com/RedHatInsights/compliance-backend/blob/a5cf3f037fb25772aa47bf7bb447d27b34ceeeae/Gemfile#L71

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions