I have an existing Rails app that’s been upgraded to Rails 7.1. I’ve created a new Fly app and have been trying to deploy for a full day with no success. I can successfully build the app and run it locally using Docker Desktop, so I know there are no simple typos or anything in the Dockerfile or other configs (I use docker compose locally in development).
When running fly deploy --no-cache
I’m getting the following exception when hitting either the assets:precompile
step or the bootsnap precompile
step (I’ve played around with different Dockerfile configurations to see if anything is improved). It seems to be failing whenever the Rails env is loaded. I don’t have any solutions, but my hypotheses on the cause are the following:
- The gems can’t be found for some reason (although it looks like
bootsnap
is found, whilemsgpack
isn’t) - It’s trying to connect to the database for some reason, and the error is a red herring. I passed in the
DATABASE_URL
as a build arg, but still got the same error.
=> ERROR [build 6/6] RUN if [ "production" != "development" ]; then SECRET 0.5s
------
> [build 6/6] RUN if [ "production" != "development" ]; then SECRET_KEY_BASE_DUMMY=1 DOCKER_BUILD=1 ./bin/rails assets:precompile; fi:
#0 0.526 <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require': /app/vendor/bundle/ruby/3.2.0/gems/msgpack-1.7.2/lib/msgpack/msgpack.so: cannot open shared object file: No such file or directory - /app/vendor/bundle/ruby/3.2.0/gems/msgpack-1.7.2/lib/msgpack/msgpack.so (LoadError)
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/msgpack-1.7.2/lib/msgpack.rb:7:in `<top (required)>'
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/store.rb:5:in `block in <top (required)>'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/explicit_require.rb:45:in `rescue in with_gems'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/explicit_require.rb:41:in `with_gems'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/store.rb:5:in `<top (required)>'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache.rb:68:in `require_relative'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache.rb:68:in `<top (required)>'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap.rb:5:in `require_relative'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap.rb:5:in `<top (required)>'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/setup.rb:3:in `require_relative'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/setup.rb:3:in `<top (required)>'
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from /app/config/boot.rb:6:in `<top (required)>'
#0 0.526 from ./bin/rails:3:in `require_relative'
#0 0.526 from ./bin/rails:3:in `<main>'
#0 0.526 <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require': /app/vendor/bundle/ruby/3.2.0/gems/msgpack-1.7.2/lib/msgpack/msgpack.so: cannot open shared object file: No such file or directory - /app/vendor/bundle/ruby/3.2.0/gems/msgpack-1.7.2/lib/msgpack/msgpack.so (LoadError)
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/msgpack-1.7.2/lib/msgpack.rb:7:in `<top (required)>'
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/store.rb:5:in `block in <top (required)>'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/explicit_require.rb:42:in `with_gems'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/store.rb:5:in `<top (required)>'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache.rb:68:in `require_relative'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache.rb:68:in `<top (required)>'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap.rb:5:in `require_relative'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap.rb:5:in `<top (required)>'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/setup.rb:3:in `require_relative'
#0 0.526 from /app/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/setup.rb:3:in `<top (required)>'
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from <internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
#0 0.526 from /app/config/boot.rb:6:in `<top (required)>'
#0 0.526 from ./bin/rails:3:in `require_relative'
#0 0.526 from ./bin/rails:3:in `<main>'
------
Error: failed to fetch an image or build from source: error building: failed to solve: executor failed running [/bin/sh -c if [ "${RAILS_ENV}" != "development" ]; then SECRET_KEY_BASE_DUMMY=1 DOCKER_BUILD=1 ./bin/rails assets:precompile; fi]: exit code: 1
fly.toml
# fly.toml app configuration file generated for rushline on 2023-11-13T13:33:59-05:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
app = "rushline"
primary_region = "yyz"
console_command = "/app/bin/rails console"
[build]
[deploy]
release_command = "/app/bin/rails db:prepare"
[env]
# WEB_CONCURRENCY = "4"
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 1
processes = ["app"]
[http_service.concurrency]
hard_limit = 25
soft_limit = 20
type = "requests"
[[statics]]
guest_path = "/app/public"
url_prefix = "/"
Dockerfile (I’ve tried a few variations, some more complicated, this is the one that’s generated from the dockerfile-rails
gem)
# syntax = docker/dockerfile:1
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.2.2
FROM ruby:$RUBY_VERSION-slim as base
# Rails app lives here
WORKDIR /app
ARG RAILS_ENV=production
ARG NODE_ENV=production
# Set production environment
ENV RAILS_ENV=${RAILS_ENV} \
NODE_ENV="${NODE_ENV}" \
BUNDLE_WITHOUT="development:test" \
BUNDLE_DEPLOYMENT="1"
# Update gems and bundler
RUN gem update --system --no-document && \
gem install -N bundler
# Install packages needed to install nodejs
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
# Install Node.js
ARG NODE_VERSION=18.16.1
ENV PATH=/usr/local/node/bin:$PATH
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
/tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
rm -rf /tmp/node-build-master
###############################################################################
# Throw-away build stages to reduce size of final image
FROM base as prebuild
# Install packages needed to build gems and node modules
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential libpq-dev libvips node-gyp pkg-config python-is-python3
###############################################################################
FROM prebuild as node
# Install yarn
ARG YARN_VERSION=3.6.1
RUN corepack enable && \
corepack prepare yarn@${YARN_VERSION} --activate
# Install node modules
COPY --link package.json yarn.lock .yarnrc.yml ./
RUN yarn install --immutable
###############################################################################
FROM prebuild as build
# Build options
ENV PATH="/usr/local/node/bin:${PATH}"
# Install application gems
COPY --link Gemfile Gemfile.lock ./
RUN bundle install && \
bundle exec bootsnap precompile --gemfile && \
rm -rf ~/.bundle/ ${BUNDLE_PATH}/ruby/*/cache ${BUNDLE_PATH}/ruby/*/bundler/gems/*/.git
# Copy node modules
COPY --from=node /app/node_modules /app/node_modules
COPY --from=node /usr/local/node /usr/local/node
ENV PATH=/usr/local/node/bin:${PATH}
# Copy application code
COPY --link . .
# Precompile bootsnap code for faster boot times
RUN bundle exec bootsnap precompile app/ lib/
# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
RUN if [ "${RAILS_ENV}" != "development" ]; then \
SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile; fi
###############################################################################
# Final stage for app image
FROM base as app
# Install packages needed for deployment
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl imagemagick libvips postgresql-client && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
# Copy built artifacts: gems, application
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /app /app
# Run and own only the runtime files as a non-root user for security
RUN useradd rails --create-home --shell /bin/bash && \
chown -R rails:rails db log tmp
USER rails:rails
# Entrypoint prepares the database.
ENTRYPOINT ["/app/bin/docker-entrypoint"]
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD ["./bin/rails", "server"]
Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.2.2"
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.1"
# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
gem "sprockets-rails"
# Use postgresql as the database for Active Record
gem "pg", "~> 1.1"
# Use the Puma web server [https://github.com/puma/puma]
gem "puma", "~> 6.0"
# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
gem "turbo-rails"
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
gem "stimulus-rails"
# Build JSON APIs with ease [https://github.com/rails/jbuilder]
gem "jbuilder"
# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
gem "bcrypt", "~> 3.1.7"
# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", require: false
# Use Redis adapter to run Action Cable in production
gem "redis", "~> 4.0"
# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
# gem "kredis"
# Provides a fast, feature rich JS bundling system [https://vite-ruby.netlify.app/guide/rails.html]
gem "vite_rails"
gem "newrelic_rpm"
gem "bugsnag"
# gem "webpacker", "~> 5.4"
gem "cssbundling-rails", "~> 1.1"
gem "autoprefixer-rails"
gem "inline_svg"
gem "friendly_id", "~> 5.4"
gem "carrierwave"
gem "carrierwave-aws"
gem "mini_magick"
gem "icalendar", require: ["icalendar", 'icalendar/tzinfo']
gem "gon", "~> 6.4.0"
gem "kaminari", "~> 1.2.0"
gem "whenever", require: false
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] # 2021: do we actually use this anywhere?
group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri mingw x64_mingw ]
end
group :development do
# Use console on exceptions pages [https://github.com/rails/web-console]
gem "web-console"
# Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
# gem "rack-mini-profiler"
# Speed up commands on slow machines / big apps [https://github.com/rails/spring]
# gem "spring"
gem "solargraph"
gem "letter_opener"
gem "rubocop-shopify", require: false
end
group :test do
# Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
gem "capybara"
gem "selenium-webdriver"
gem "webdrivers"
# Spec Setup
gem "rspec-rails", "~> 6.0.3"
gem "factory_bot_rails", "~> 6.2.0"
# Additional Testing Gems
gem "shoulda-matchers"
gem "rack_session_access" # why do we need this?
gem "timecop"
gem "faker"
end
Any help is greatly appreciated!