Skip to content

Instantly share code, notes, and snippets.

@sbounmy
Last active March 31, 2024 09:38
Show Gist options
  • Save sbounmy/75b35b569f45321e4f7b7287130912f7 to your computer and use it in GitHub Desktop.
Save sbounmy/75b35b569f45321e4f7b7287130912f7 to your computer and use it in GitHub Desktop.
Files to deploy Rails 7 app with Kamal
KAMAL_REGISTRY_PASSWORD=xxx
RAILS_MASTER_KEY=xxxxxxxxxxxxxxx
POSTGRES_PASSWORD=xxxxxxxxxxxxx
REDIS_PASSWORD=my-redis-password
REDIS_URL=redis://:my-redis-password@n28-redis:6379/1
# Deploy to these servers.
servers:
web:
hosts:
- 123.123.123.123
options:
network: "private"
job:
hosts:
- 123.123.123.123
# Or something like bin/job
cmd: bin/bundle exec sidekiq
# Limit workers resources
options:
cpus: 1
network: "private"
# Inject ENV variables into containers (secrets come from .env).
# Remember to run `kamal env push` after making changes!
env:
clear:
DB_HOST: 123.123.123.123
POSTGRES_DB: xxx_production
POSTGRES_USER: xxx
RAILS_LOG_TO_STDOUT: 1
RAILS_SERVE_STATIC_FILES: 1
secret:
- RAILS_MASTER_KEY
- POSTGRES_PASSWORD
# Use a different ssh user than root
# ssh:
# user: app
builder:
dockerfile: production.Dockerfile
accessories:
db:
host: 123.123.123.123
image: postgres:15
port: 5432
env:
clear:
POSTGRES_DB: xxx_production
POSTGRES_USER: xxx
secret:
- POSTGRES_PASSWORD
directories:
- data:/var/lib/postgresql/data
files:
# - config/postgres/production.cnf:/etc/postgresql/my.conf
- db/production.sql:/docker-entrypoint-initdb.d/setup.sql
redis:
image: "redis:7"
cmd: "/bin/sh -c 'redis-server --requirepass $REDIS_PASSWORD'"
env:
secret:
- REDIS_PASSWORD
roles:
- web
- job
port: 6379
volumes:
- /var/lib/redis:/data
options:
network: "private"
traefik:
options:
network: "private"
publish:
- "443:443"
volume:
- "/letsencrypt/acme.json:/letsencrypt/acme.json"
args:
entryPoints.web.address: ":80"
entryPoints.websecure.address: ":443"
entryPoints.web.http.redirections.entryPoint.to: websecure
entryPoints.web.http.redirections.entryPoint.scheme: https
entryPoints.web.http.redirections.entrypoint.permanent: true
# Rails file storage
volumes:
- storage:/rails/storage
# Name of your application. Used to uniquely configure containers.
service: n28
# Name of the container image.
image: hackerhouse/n28
# Credentials for your image host.
registry:
# Specify the registry server, if you're not using Docker Hub
# server: registry.digitalocean.com / ghcr.io / ...
username: stephane@xxx.com
# Always use an access token rather than real password when possible.
password:
- KAMAL_REGISTRY_PASSWORD
# Use a different ssh user than root
# ssh:
# user: app
builder:
dockerfile: production.Dockerfile
accessories:
db:
image: postgres:15
port: 5432
env:
clear:
POSTGRES_USER: n28
directories:
- data:/var/lib/postgresql/data
files:
- config/postgres/production.cnf:/etc/postgresql/my.conf
- db/production.sql:/docker-entrypoint-initdb.d/setup.sql
healthcheck:
path: /up
port: 3000
max_attempts: 10
interval: 3s
log_lines: 10_000
# in ./rails/bin/docker-entrypoint
#!/bin/bash -e
# If running the rails server then create or migrate existing database
if [ "${1}" == "./bin/rails" ] && [ "${2}" == "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
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential git libvips pkg-config libpq-dev
# 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
# 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 postgresql-client 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"]
CREATE DATABASE xxx_production;
@sbounmy
Copy link
Author

sbounmy commented Oct 26, 2023

kamal setup -d production
kamal deploy -d production

@poudelprakash
Copy link

content for config/postgres/production.cnf?
you have it enabled on https://gist.github.com/sbounmy/75b35b569f45321e4f7b7287130912f7#file-deploy-yml-L34

@sbounmy
Copy link
Author

sbounmy commented Nov 7, 2023

content for config/postgres/production.cnf? you have it enabled on https://gist.github.com/sbounmy/75b35b569f45321e4f7b7287130912f7#file-deploy-yml-L34

I actually dont have any content it was part of the configuration. but I do have a production.sql file

CREATE DATABASE {{replace_by_database_name}};

@sbounmy
Copy link
Author

sbounmy commented Dec 27, 2023

updated with sidekid / redis

make sure to create the private network with docker network create -d bridge private on the host (via ssh)

inspired from https://nts.strzibny.name/deploying-rails-single-server-kamal/

@sbounmy
Copy link
Author

sbounmy commented Jan 10, 2024

added missing file docker-entry-point. you might want to not add it as it will automatically run migration on kamal deploy

I would suggest to run manually migration with kamal app exec "rake db:prepare"

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