Reputation: 403
I deploy like this:
bundle exec cap deploy:cold
RAILS_ENV=production rake db:migrate
bundle exec cap deploy:migrate
Error in log file:
I, [2014-04-14T14:15:14.853543 #10769] INFO -- : Started GET "/users/sign_up" for
176.192.228.14 at 2014-04-14 14:15:14 -0400
I, [2014-04-14T14:15:14.856055 #10769] INFO -- : Processing by
Devise::RegistrationsController#new as HTML
I, [2014-04-14T14:15:14.857398 #10769] INFO -- : Completed 500 Internal Server Error
in 1ms
F, [2014-04-14T14:15:14.860844 #10769] FATAL -- :
ActiveRecord::StatementInvalid (Could not find table 'users')
But in the current/db folder was created production.sqlite3. On localhost:3000 it works. How can I migrate the database for production with Capistrano?
I use Nginx and Unicorn and this is my repository.
Upvotes: 2
Views: 1663
Reputation: 1615
There are two good options for this; Copying or Linking. Here are some reasons to choose one or the other, followed by how to do it with modern, or not so modern, Rails.
Copying:
Linking:
My guess is that most people who choose SQLite do so for ease of administration in which case copying the database is probably the right option, if you can afford the space. Assuming you have Capistrano set to only keep 5 releases and your database isn't huge, this should be very doable.
If you built your deploy workflow from scratch, you can simply add a new copy_db
task and tell it to run before you run db:migrate
:
task :copy_db, roles: :app do
run "cp #{current_path}/storage/production.sqlite3 #{release_path}/storage/"
# For Rails < 7.1:
# run "cp #{current_path}/db/production.sqlite3 #{release_path}/db/"
end
If you're using the capistrano-rails gem, you can create the task and have it run before every deploy:migrate
using a before
hook:
# lib/capistrano/tasks/copy_db.rake
namespace :deploy do
desc "Copy the database from the current deploy to the new release"
task :copy_db, roles(:app) do
run "cp #{current_path}/storage/production.sqlite3 #{release_path}/storage/"
end
before 'deploy:migrate', 'deploy:copy_db'
end
Use append :linked_dirs to link the storage/
folder in your deploy to the shared folder. To do this add append :linked_dirs, "storage"
to your config/deploy.rb
or config/deploy/<stage_name>.rb
file.
You may already have this command to link your log/
or .bundle/
folders in which case you can just add "storage" to the end of the list:
If you're on Rails < 7.1 the database lives in the db/
directory and you probably don't want to link the whole directory. In that case you can just link the database file by adding append :linked_files, "db/production.sqlite3"
to your config/deploy.rb
or config/deploy/<stage_name>.rb
file.
Remember, just like if you're using a shared Postgres/MySQL database, if you rollback your deploy, you may need to rollback your database migrations too. One way to handle this could be to add a rollback_db
task and set it to automatically run after rollback with:
after 'deploy:reverted', 'deploy:rollback_db'
If you want the best (worst?) of both worlds you could link the storage/
folder and make a copy of the database in that folder (named for the release) every time you deploy. It would also be up to you to delete excess copies of the database, probably after deploy:cleanup
. Checkout the deploy:cleanup
task for a pattern of how to go about that.
Upvotes: 0
Reputation: 2874
Better yet, change up your db configuration:
production:
adapter: sqlite3
database: /absolute/path/to/shared/db/production.sqlite3 # instead of db/production.sqlite3
Upvotes: 7
Reputation: 2129
Working with Sqlite in production is very problematic because each time you deploy new version you entiredb is stay on the old release folder, what you can do is when you deploy add this command:
task :copy_sqlite, roles: :app do
run "cp #{current_path}/db/production.sqlite3 #{release_path}/db/"
end
just add this the before rake db:migrate
and it will solve your problem.
My strong suggestion move to PostgreSQL/MySQL.
Upvotes: 3