SQLite is the new (cool) kid on the Rails block, and rightly so!
I just migrated one of our Rails apps from Postgres to SQLite, and here are some quick notes on how to make it work on dokku.
The TLDR is that you have to mount a host directory into your dokku app, as otherwise your SQLite database file gets lost (= deleted) every time you deploy a new version of your app. Losing all data on every deploy would be a rather suboptimal user experience, nervous chuckle.. so here’s how you solve that:
Use SQLite In Dokku By Mounting Persistent Storage
Dokku outlines persistent storage in the docs here. For Rails 8 using SQLite, here’s what you need to do. Let’s assume your dokku app is called rails_app:
dokku storage:ensure-directory rails_app
=> /var/lib/dokku/data/storage/rails_app/
What has happened behind the scenes is that dokku created the rails_app folder above and set the correct permissions. This will be the directory on your host OS (= your server) which will be mounted into your Rails app.
Next up, you actually have to mount that directory in your Rails app, and select where to mount it there. Here’s my suggestion:
dokku storage:mount rails_app /var/lib/dokku/data/storage/rails_app:/app/storage
So the idea is that you’re mounting the host directory (var/lib/dokku/...) into /app/storage. Not that /app is where dokku copies your Rails app into, this is not specific to Rails. So the /app directory is the root of your Rails project, i.e. it contains the typical folders config, db, app (<– don’t get confused), etc.
The /app/storage directory is actually what you see in development, too, as rails new creates a storage directory for your development SQLite database. So the cool thing here is that we’re essentially following the Rails conventions of storing your production database in the same directory on the server.
Next up, you need to make the appropriate changes to your config/database.yml file – none of these are dokku-specific, only the path to the database file is:
# This section is unchanged
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
# This section is also unchanged. Note that we use "primary" here in case you'd be adding solid queue in dev, which would be added under the "queue" key.
development:
primary:
<<: *default
database: storage/development.sqlite3
# This section is changed - we changed the "database" path below.
production:
primary:
<<: *default
# Points to our ./storage directory.
database: storage/production.sqlite3
# Here's an example how a solid queue setup would look on dokku - simply storage the SQLite db in the same storage/ directory, but give it a different filename of course.
queue:
<<: *default
database: storage/production_queue.sqlite3
migrations_paths: db/queue_migrate
And that’s it!
Creating SQLite Databases In Dokku App
After your first deploy, which will likely not run smoothly (migrations won’t run, database is missing, everything blows up, etc., you know how it goes on first deploys) you’d need to actually create the databases like so:
# Assuming your worker is called "web" in your Procfile
dokku enter rails_app web
rails db:create db:migrate
# Solid queue peculiarity: Use db:prepare to create the db
rails db:prepare
Solid queue is a bit weird here, as it seems to introduce the new convention of not adding migration files to your project (like ActionText, Active Storage, etc.) but instead adds a queue_schema.rb file in the db/ directory. Hm. So, to create the solid queue tables, you have to run db:prepare.
For your next deploy, you can modify your Procfile as follows:
Fixing The Procfile
release: rails db:migrate
web: bundle exec puma -C config/puma.rb
The idea here is that, from now on, migrations run on each deploy (because your database files actually exist, which is nice to have if you want any migrations, chuckle), and your web server actually starts (useful, too).
Did I miss anything? Let me know in the comments. The db:prepare convention for the solid stack is a bit weird. Maybe I’ll find a more elegant solution for it.
Leave a Reply