Skip to content

Instantly share code, notes, and snippets.

@tobi
Created January 1, 2022 01:53
Show Gist options
  • Star 87 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save tobi/7fcd2004fb5ee974e5ffcf5fef48edfe to your computer and use it in GitHub Desktop.
Save tobi/7fcd2004fb5ee974e5ffcf5fef48edfe to your computer and use it in GitHub Desktop.
# Rails production setup via SQLite3 made durable by https://litestream.io/
# Copy this to Dockerfile on a fresh rails app. Deploy to fly.io or any other container engine.
#
# try locally: docker build . -t rails && docker run -p3000:3000 -it rails
#
# in production you might want to map /data to somewhere on the host,
# but you don't have to!
#
FROM ruby:3.0.2
# use https://github.com/benbjohnson/litestream/releases/download/v0.3.7/litestream-v0.3.7-linux-amd64-static.tar.gz on intel
ADD https://github.com/benbjohnson/litestream/releases/download/v0.3.7/litestream-v0.3.7-linux-arm64-static.tar.gz /tmp/litestream.tar.gz
RUN tar -C /usr/local/bin -xzf /tmp/litestream.tar.gz
ENV RAILS_ENV 'production'
ENV DB_PATH '/data/production.sqlite3'
# find a REPLICA_URL host/keys setup for persisting your sqlite3 database ( https://litestream.io/guides/ )
# supports sftp, s3, azure, google cloud storage, backblaze, etc. you probably have an account
# already
ENV REPLICA_URL 's3://<your-url>/db.sqlite3'
ENV LITESTREAM_ACCESS_KEY_ID '<your-access-key-id>'
ENV LITESTREAM_SECRET_ACCESS_KEY '<your-secret-access-key>'
# get dependencies
WORKDIR /app
ADD Gemfile /app/
ADD Gemfile.lock /app/
RUN bundle install
# add code (and bundle)
ADD . /app
RUN bundle exec rake assets:precompile
# rails expects production.sqlite3 to be in db/production.sqlite3
RUN ln -nfs $DB_PATH /app/db/production.sqlite3
EXPOSE 3000
CMD \
# if the db file doesn't exist we get it from the REPLICA_URL
[ ! -f $DB_PATH ] && litestream restore -v -if-replica-exists -o $DB_PATH "${REPLICA_URL}" \
# then we run the migrations
; bundle exec rake db:migrate \
# then we launch replicate and execute rails server
; litestream replicate -exec "bundle exec rails server -p 3000" $DB_PATH $REPLICA_URL
@tobi
Copy link
Author

tobi commented Jan 1, 2022 via email

@karinajf
Copy link

Gives me error when trying to deploy to fly.io:

Preparing to run: `/bin/sh -c [ ! -f $DB_PATH ] && litestream restore -v -if-replica-exists -o $DB_PATH "${REPLICA_URL}"   ; bundle exec rake db:migrate   ; litestream replicate -exec "bundle exec rails server -p 3000" $DB_PATH $REPLICA_URL` as root
2022/01/28 21:01:17 listening on [fdaa:0:4871:a7b:2656:7bd2:6dc4:2]:22 (DNS: [fdaa::3]:53)
 /bin/sh: 1: litestream: Exec format error
rake aborted!
SQLite3::CantOpenException: unable to open database file

I added the REPLICA_URL, LITESTREAM_ACCESS_KEY_ID and LITESTREAM_SECRET_ACCESS_KEY
Do I have to do something else before deploying it?

@sleroux
Copy link

sleroux commented May 30, 2022

👋 Hey Karina,

The error here:

/bin/sh: 1: litestream: Exec format error

Indicates that you're using the wrong CPU arch for Litestream. You'll want to uncomment line 11 and use that instead of line 10 as you're most likely running this not on a M1 macbook.

Maybe not related but the other issue that I ran into today when I was playing around with it is that the symlink on line 36 is linking from DB_PATH (/data/production.sqlite3) -> db/production.sqlite3 but if you didn't have a previous backup available on your storage provider the bundle exec rake db:migrate task will fail as the database is actually not a database but an empty symlink. To kickstart this I ended up doing the following:

  1. Run RAILS_ENV=production bundle exec rake db:create db:migrate to setup your production database locally if you don't have one.
  2. Run sqlite3 db/production.sqlite3 to setup WAL journalling (PRAGMA journal_mode=WAL;) as you'll need this for Litestream to work.
  3. Run the replicate command litestream replicate /db/production.sqlite3 $REPLICA_URL to copy it over to your storage provider

After that you'll have an empty copy of production on your replica that should be able to be pulled down when you start up the Docker process the next time and anytime after that.

Anyways thought I'd drop a note as I ran into the same line of issues today and this would have saved me some time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment