A couple issues with the Dockerfile generated for a Rails-detected app

Hi. I tried Fly out today for the first time to deploy a Rails app and encountered a couple build issues with the Dockerfile flyctl launch generated.

The first is an odd error caused by having the net-http gem added to my Gemfile, which due to some peculiarity with the Docker build caused this error:

bundler: failed to load command: rails (/app/vendor/bundle/ruby/2.7.0/bin/rails)
Gem::LoadError: You have already activated uri 0.10.0, but your Gemfile requires uri 0.11.0. Since uri is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports uri as a default gem.

I say odd because updating the RubyGems gem from the default version in the Docker image (v3.1.6) to the latest version fixes the problem, but I can’t reproduce the error on my local development machine with the old RubyGems version.

In the course of debugging the problem I also noticed that while the Dockerfile updates bundler before installing gems:

RUN gem install -N bundler -v ${BUNDLER_VERSION}

This doesn’t stick in the final Docker image because the changed bundler files aren’t copied out of the gems stage of the build. IMO it’s best practice to be executing bundle exec with the version of bundler required in the Gemfile.

I made these changes to the Dockerfile to fix these issues:

diff --git a/Dockerfile b/Dockerfile
index 69f21c8..ae833a6 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -44,7 +44,8 @@ RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
 
 FROM build_deps as gems
 
-RUN gem install -N bundler -v ${BUNDLER_VERSION}
+RUN gem update --system --no-document && \
+    gem install -N bundler -v ${BUNDLER_VERSION}
 
 COPY Gemfile* ./
 RUN bundle install &&  rm -rf vendor/bundle/ruby/*/cache
@@ -76,6 +77,8 @@ RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \
 
 COPY --from=gems /app /app
 COPY --from=node_modules /app/node_modules /app/node_modules
+COPY --from=gems /usr/lib/fullstaq-ruby/versions /usr/lib/fullstaq-ruby/versions
+COPY --from=gems /usr/local/bundle /usr/local/bundle
 
 ENV SECRET_KEY_BASE 1

I made a reproducible GitHub repo for anyone interested: GitHub - abevoelker/fly-rails-broken-build-repro

With my fix on the fix branch: Fix Docker build · abevoelker/fly-rails-broken-build-repro@b2d01de · GitHub

These is how I was building the image locally to test:

$ DOCKER_BUILDKIT=1 docker build --build-arg BUNDLER_VERSION="2.3.19" --build-arg NODE_VERSION="14" --build-arg RUBY_VERSION="2.7.6" -t app .

(Ofc it was the same errors doing the remote build with fly deploy --remote-only)

3 Likes

Oh this is great! Thanks for the diffs!

Thanks ! I had the issue and it helped !

Thank you, @GabeMeister!

I tried to deploy a dummy app and got the following error:

 => ERROR [stage-4 5/5] RUN bin/rails fly:build                                                                                                                                                                                                                            ------
 > [stage-4 5/5] RUN bin/rails fly:build:
#23 0.304 Activating bundler (2.3.20) failed:
#23 0.304 Could not find 'bundler' (= 2.3.20) - did find: [bundler-2.3.7]
#23 0.304 Checked in 'GEM_PATH=/root/.local/share/gem/ruby/3.1.0:/usr/lib/fullstaq-ruby/versions/3.1.2-jemalloc/lib/ruby/gems/3.1.0:/usr/local/bundle' , execute `gem env` for more information
#23 0.304
#23 0.304 To install the version of bundler this project requires, run `gem install bundler -v '2.3.20'`
------
Error failed to fetch an image or build from source: error building: executor failed running [/bin/bash -c bin/rails fly:build]: exit code: 42

Your changed to the Dockerfile fixed this error. :pray:

These changes to the Dockerfile will be included in flyctl v0.0.389 once it becomes available. Thanks!