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
)