Skip to content

Instantly share code, notes, and snippets.

@robzolkos
Last active March 2, 2024 20:59
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save robzolkos/96ca00b56dee3f6ba7207ef57fceaa9c to your computer and use it in GitHub Desktop.
Save robzolkos/96ca00b56dee3f6ba7207ef57fceaa9c to your computer and use it in GitHub Desktop.
Kamal / SQLite3 issue
# SQLite. Versions 3.8.0 and up are supported.
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem "sqlite3"
#
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
development:
<<: *default
database: data/development.sqlite3
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: data/test.sqlite3
production:
<<: *default
database: /data/production.sqlite3
service: <app name>
image: <image>
servers:
- <server ip>
registry:
server: registry.digitalocean.com
username:
- KAMAL_REGISTRY_PASSWORD
password:
- KAMAL_REGISTRY_PASSWORD
env:
secret:
- RAILS_MASTER_KEY
volumes:
- data:/data
#!/bin/bash -e
# If running the rails server then create or migrate existing database
if [ "${*}" == "./bin/rails server" ]; then
./bin/rails db:prepare
fi
exec "${@}"
# syntax = docker/dockerfile:1
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.2.2
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
# Rails app lives here
WORKDIR /rails
# Set production environment
ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development"
# 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 git libvips node-gyp pkg-config python-is-python3
# Install JavaScript dependencies
ARG NODE_VERSION=18.17.1
ARG YARN_VERSION=1.22.19
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 && \
npm install -g yarn@$YARN_VERSION && \
rm -rf /tmp/node-build-master
# Install application gems
COPY Gemfile Gemfile.lock ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
bundle exec bootsnap precompile --gemfile
# Install node modules
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
# Copy application code
COPY . .
# 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=1 ./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 libsqlite3-0 libvips && \
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
RUN useradd rails --create-home --shell /bin/bash && \
chown -R rails:rails db log storage tmp
USER rails:rails
# 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"]
@robzolkos
Copy link
Author

The exception

ActiveRecord::StatementInvalid: SQLite3::CantOpenException: unable to open database file


Caused by:
SQLite3::CantOpenException: unable to open database file

Tasks: TOP => db:prepare
(See full trace by running task with --trace)

@clayton
Copy link

clayton commented Sep 24, 2023

@robzolkos My Dockerfile has a slight difference:

EXPOSE 3000
###  I generated mine using `dockerfile-rails --sqlite3` and it added this line
VOLUME /data 
###
CMD ["./bin/rails", "server"]

@condef5
Copy link

condef5 commented Sep 24, 2023

Well I finally have been able to deploy it, it was a permission issue with data directory:

# dockerfile#66

RUN useradd rails --create-home --shell /bin/bash && \
    chown -R rails:rails db log storage data tmp

And also you need to update the volumen parts, adding the rails directory before data :)

# deploy.yml#18

volumes:
  - "data:/rails/data"

@clayton
Copy link

clayton commented Sep 24, 2023

Not confidence inspiring that mine looks different but works just the same 😅

For what it's worth, my useradd and permissions stuff:

RUN useradd rails --create-home --shell /bin/bash && \
    mkdir /data && \
    chown -R rails:rails db log storage tmp /data

Note that it's making rails the owner of /data not just data (which would be in the working /rails directory as /rails/data)

Which means that my deploy.yml looks like:

volumes:
  - "data:/data" 

I believe that using the root data directory (i.e. /data not /rails/data) was the key for persistent data between deployments. When I was trying to use the /rails working directory, my DB would get wiped out on each deploy.

YMMV!

@johannesschobel
Copy link

oh man.. thanks a lot. this GIST helped me a lot! You guys are awesome - thank you for providing the proper details.
I also had the same issue as described above - the proper solution was to add the directory to the chown command!

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