I’ve tried for days to deploy a new version of an already running production application (Rails 7) an it doesn’t work. The app was set up about 8 months ago and has been automatically migrated to the fly.io V2 platform a few days ago. This is the output I get every single time and yes, the fly.rake file exists and can be executed locally without any issues:
Running my-secret-app-name release_command: bin/rails fly:release
Waiting for 5683d52ea1078e to get exit event
Error release_command failed running on machine 5683d52ea1078e with exit code 1.
Check its logs: here's the last 100 lines below, or run 'fly logs -i 5683d52ea1078e':
Pulling container image registry.fly.io/my-secret-app-name:deployment-01H77P4S2GJMXWQQMF4HM9DABF
Successfully prepared image registry.fly.io/my-secret-app-name:deployment-01H77P4S2GJMXWQQMF4HM9DABF (5.804098525s)
Configuring firecracker
[ 0.050155] PCI: Fatal: No config space access function found
INFO Starting init (commit: b437b5b)...
INFO Preparing to run: `/rails/bin/docker-entrypoint bin/rails fly:release` as rails
INFO [fly api proxy] listening at /.fly/api
2023/08/07 09:45:50 listening on [fdaa:1:3a4:a7b:1c2:f8b:6a3b:2]:22 (DNS: [fdaa::3]:53)
rails aborted!
LoadError: cannot load such file -- /rails/lib/tasks/fly.rake
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/engine.rb:661:in `load'
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/engine.rb:661:in `block in run_tasks_blocks'
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/engine.rb:661:in `each'
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/engine.rb:661:in `run_tasks_blocks'
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/application.rb:501:in `run_tasks_blocks'
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/engine.rb:464:in `load_tasks'
/rails/Rakefile:10:in `<main>'
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/commands/rake/rake_command.rb:20:in `block in perform'
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/commands/rake/rake_command.rb:18:in `perform'
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/command.rb:51:in `invoke'
/rails/vendor/bundle/ruby/3.2.0/gems/railties-7.0.6/lib/rails/commands.rb:18:in `<main>'
<internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
<internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:38:in `require'
/rails/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/rails/bin/rails:4:in `<main>'
(See full trace by running task with --trace)
INFO Main child exited normally with code: 1
INFO Starting clean up.
WARN hallpass exited, pid: 257, status: signal: 15 (SIGTERM)
2023/08/07 09:45:51 listening on [fdaa:1:3a4:a7b:1c2:f8b:6a3b:2]:22 (DNS: [fdaa::3]:53)
[ 2.300466] reboot: Restarting system
machine restart policy set to 'no', not restarting
Error: release command failed - aborting deployment. error release_command machine 5683d52ea1078e exited with non-zero status of 1
(“my-secret-app-name” is not the real name of the app!)
This is what I did:
fly config save
rails generate dockerfile --compose
fly.toml:
# fly.toml app configuration file generated for my-secret-app-name on 2023-08-04T11:57:45+02:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
app = "my-secret-app-name"
primary_region = "fra"
kill_signal = "SIGINT"
kill_timeout = "5s"
[experimental]
auto_rollback = true
[build]
[build.args]
BUILD_COMMAND = "bin/rails fly:build"
SERVER_COMMAND = "bin/rails fly:server"
[deploy]
release_command = "bin/rails fly:release"
[env]
PORT = "8080"
[[mounts]]
source = "riedl_konfigurator_data"
destination = "/data"
processes = ["app"]
[[services]]
protocol = "tcp"
internal_port = 8080
processes = ["app"]
[[services.ports]]
port = 80
handlers = ["http"]
force_https = true
[[services.ports]]
port = 443
handlers = ["tls", "http"]
[services.concurrency]
type = "connections"
hard_limit = 25
soft_limit = 20
[[services.tcp_checks]]
interval = "15s"
timeout = "2s"
grace_period = "1s"
[[statics]]
guest_path = "/app/public"
url_prefix = "/"
fly.rake:
# frozen_string_literal: true
# commands used to deploy a Rails application
namespace :fly do
# BUILD step:
# - changes to the filesystem made here DO get deployed
# - NO access to secrets, volumes, databases
# - Failures here prevent deployment
task :build => "assets:precompile"
# RELEASE step:
# - changes to the filesystem made here are DISCARDED
# - full access to secrets, databases
# - failures here prevent deployment
task :release => "db:migrate"
# SERVER step:
# - changes to the filesystem made here are deployed
# - full access to secrets, databases
# - failures here result in VM being stated, shutdown, and rolled back
# to last successful deploy (if any).
task :server => :swapfile do
sh "bin/rails server"
end
# optional SWAPFILE task:
# - adjust fallocate size as needed
# - performance critical applications should scale memory to the
# point where swap is rarely used. 'fly scale help' for details.
# - disable by removing dependency on the :server task, thus:
# task :server do
task :swapfile do
sh "fallocate -l 512M /swapfile"
sh "chmod 0600 /swapfile"
sh "mkswap /swapfile"
sh "echo 10 > /proc/sys/vm/swappiness"
sh "swapon /swapfile"
end
end
Dockerfile (No changes):
# syntax = docker/dockerfile:1
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.2.1
FROM ruby:$RUBY_VERSION-slim as base
# Rails app lives here
WORKDIR /rails
# Set production environment
ENV RAILS_ENV="production" \
BUNDLE_WITHOUT="development:test" \
BUNDLE_DEPLOYMENT="1"
# Update gems and bundler
RUN gem update --system --no-document && \
gem install -N bundler
# Throw-away build stage to reduce size of final image
FROM base as build
# Install packages needed to build gems and node modules
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential curl libpq-dev libvips node-gyp pkg-config python-is-python3
# Install JavaScript dependencies
ARG NODE_VERSION=16.16.0
ARG YARN_VERSION=3.6.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 && \
corepack enable && \
corepack prepare yarn@$YARN_VERSION --activate && \
rm -rf /tmp/node-build-master
# 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
# Install node modules
COPY --link package.json yarn.lock ./
RUN yarn install --frozen-lockfile
# 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 SECRET_KEY_BASE=DUMMY ./bin/rails assets:precompile
# Final stage for app image
FROM base
# 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 /rails /rails
# Run and own only the runtime files as a non-root user for security
ARG UID=1000 \
GID=1000
RUN groupadd -f -g $GID rails && \
useradd -u $UID -g $GID rails --create-home --shell /bin/bash && \
chown -R rails:rails db log storage tmp
USER rails:rails
# Deployment options
ENV RAILS_LOG_TO_STDOUT="1" \
RAILS_SERVE_STATIC_FILES="true"
# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD ["./bin/rails", "server"]
I also tried to add this to production.rb
:
config.eager_load = true # Was already there
config.rake_eager_load = true
And this to the application.rb
:
config.eager_load_paths << Rails.root.join("lib")
config.eager_load_paths << Rails.root.join("lib/tasks")
config.enable_dependency_loading = true
config.autoload_paths << Rails.root.join("lib")
config.autoload_paths << Rails.root.join("lib/tasks")
Nothing works and its driving me crazy!