SQLite is very useful for rapid prototyping. It’s commonly used locally but it can also be used on remote servers. If you’re using Capistrano to manage server deployments then you’ll need to handle SQLite’s database file.
How Capistrano releases work
Capistrano works by creating a new directory for each release and creating a symlink for the latest (current) release. Here’s how the directory structure looks:
1
2
3
4
5
6
7
8
9
10
11
12
├── current -> /var/www/my_app_name/releases/20150120114500/
├── releases
│ ├── 20150080072500
│ ├── 20150090083000
│ ├── 20150100093500
│ ├── 20150110104000
│ └── 20150120114500
├── repo
│ └── <VCS related data>
├── revisions.log
└── shared
└── <linked_files and linked_dirs>
SQLite’s database file is typically stored inside the Rails db
directory. Because each deployment is created in a new directory, the database file gets ‘lost’ on each deploy.
Copying the DB
The obvious way to handle this problem is to copy the database file across, each time a new release is created. Here’s how the code for that looks:
1
2
3
4
5
6
7
8
9
namespace :deploy do
task :copy_sqlite do
on roles(:all) do |_host|
execute "cp #{current_path}/db/production.sqlite3 #{release_path}/db/"
end
end
end
after 'deploy:updated', 'deploy:copy_sqlite'
Using the shared directory
However, there are some drawbacks to this approach. Firstly, it duplicates the database each time, spreading data and taking up server space. Secondly, it breaks Capistrano’s rollback feature because rolling back would revert to an older version of the database.
Luckily, there is a better way to fix the problem, using linked_dirs
. Here’s how the code for that looks:
1
set :linked_dirs, %w[db/production.sqlite3]
This will move production.sqlite3
into the shared
directory, which persists between releases. The current release will have a symlink that points to it. With this code you don’t need to worry about copying the database, the current release will always have access to production.sqlite3
.