Skip to content

Instantly share code, notes, and snippets.

@zealot128
Last active March 30, 2023 14:35
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save zealot128/7967319431b7d5f621fb66979e95b1d2 to your computer and use it in GitHub Desktop.
Mrsk Deployment example
# See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files.
# Ignore git directory.
/.git/
# Ignore bundler config.
/.bundle
# Ignore all default key files.
/config/master.key
/config/credentials/*.key
# Ignore all environment files.
/.env*
!/.env.example
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# Ignore pidfiles, but keep the directory.
/tmp/pids/*
!/tmp/pids/
!/tmp/pids/.keep
# Ignore storage (uploaded files in development and any SQLite databases).
/storage/*
!/storage/.keep
/tmp/storage/*
!/tmp/storage/
!/tmp/storage/.keep
spec
# Ignore assets.
/node_modules/
/app/assets/builds/*
!/app/assets/builds/.keep
/public/assets
/public/uploads
/public/system
/public/vite-dev
/public/vite-test
/public/packs
/data.ms
config/deploy.rb
Dockerfile
/coverage
/*.md
MRSK_REGISTRY_PASSWORD=YourGitlabOrDockerRegistrationPassword
SECRET_KEY_BASE=UseThis
RAILS_MASTER_KEY=UseThisIfYouUseCredentials.enc
# config/deploy.yml
# Name of your application. Used to uniquely configure containers.
service: workinde
# Name of the container image.
image: myorg/myproject
# Deploy to these servers.
servers:
web:
hosts:
- 123.123.123.123
options:
# add the host ip, so the containers can reach each other without docker-compose by using
# postgres://host.docker.internal/.. etc.
add-host: host.docker.internal:host-gateway
job:
hosts:
- 123.123.123.123
cmd: >
/bin/bash -l -c 'bundle exec whenever --update-crontab && bundle exec sidekiq -C config/sidekiq.yml'
port: false
options:
add-host: host.docker.internal:host-gateway
# Credentials for your image host.
registry:
# use docker reg, gitlab etc.
server: registry.gitlab.com
username: yourUsername
password:
- MRSK_REGISTRY_PASSWORD
env:
clear:
DATABASE_URL: postgres://postgres@host.docker.internal:5432/app
REDIS_URL: redis://host.docker.internal:6379/0
RAILS_SERVE_STATIC_FILES: "true"
RAILS_LOG_TO_STDOUT: "true"
RAILS_ENV: production
secret:
- SECRET_KEY_BASE
volumes:
- "/opt/app_system:/rails/public/system"
# also mount /backup, so we can easily dump/import pg stuff etc.
- "/backup:/backup"
# Call a broadcast command on deploys.
# audit_broadcast_cmd:
# bin/broadcast_to_bc
builder:
args:
RUBY_VERSION: 3.2.1
UID: 1000
GID: 1000
RAILS_ENV: production
#secrets:
# - GITHUB_TOKEN
remote:
arch: amd64
# set this or DOCKER_HOST env:
host: ssh://root@123.123.123.123
accessories:
db:
image: groonga/pgroonga:2.4.5-alpine-12
hosts:
- 123.123.123.123
env: {}
# you can also just use :5432 BUT then the host is reachable via public internet if NO FIREWALL ENABLED!
# I just use the docker main ip here.
port: "172.17.0.1:5432:5432"
directories:
- data:/var/lib/postgresql/data
env:
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7.0
hosts:
- 123.123.123.123
port: "172.17.0.1:6379:6379"
directories:
- data:/data
traefik:
# I also don't want to bind to 0.0.0.0
# but just bind to the vpn which Hetzner provided me with
host_port: "10.90.90.10:80"
# Configure a custom healthcheck (default is /up on port 3000)
# healthcheck:
# path: /healthz
# port: 4000
#!/bin/bash -e
# put in bin/docker-entrypoint and make chmod +x
# 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.1
FROM ruby:$RUBY_VERSION-slim as base
# Rails app lives here
WORKDIR /rails
# imagemagick AND vips, usually only one is needed.
ENV RUNTIME_DEPS="curl gnupg2 libvips libvips-dev tzdata imagemagick librsvg2-dev libmagickwand-dev postgresql-client" \
BUILD_DEPS="build-essential libpq-dev git less pkg-config python-is-python3 node-gyp vim rsync"
# Throw-away build stage to reduce size of final image
FROM base as build
# Common dependencies
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=tmpfs,target=/var/log \
rm -f /etc/apt/apt.conf.d/docker-clean; \
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache; \
apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends $BUILD_DEPS $RUNTIME_DEPS
# Install JavaScript dependencies
ARG NODE_VERSION=14.21.3
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
# COPY Aptfile /tmp/Aptfile
# RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
# --mount=type=cache,target=/var/lib/apt,sharing=locked \
# --mount=type=tmpfs,target=/var/log \
# apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get -yq dist-upgrade && \
# DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
# $(grep -Ev '^\s*#' /tmp/Aptfile | xargs)
# Set production environment
ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_JOBS="4" \
BUNDLE_NO_CACHE="true" \
BUNDLE_WITHOUT="development,test" \
GEM_HOME="/usr/local/bundle"
# Install application gems
COPY Gemfile Gemfile.lock ./
RUN --mount=type=cache,target=~/.bundle/cache \
bundle config --local deployment 'true' \
&& bundle config --local path "${BUNDLE_PATH}" \
&& 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/
# reduce node memory usage:
ENV NODE_OPTIONS="--max-old-space-size=4096"
ARG DATABASE_URL="postgres://postgres:postgres@db:5432/postgres"
# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
# Mount node_modules and tmp/cache/vite as cache volume:
RUN --mount=type=cache,target=/rails/node_modules \
--mount=type=cache,target=/rails/tmp/cache/vite \
--mount=type=cache,target=/rails/tmp/cache/assets \
--mount=type=cache,target=/rails/tmp/assets_between_runs \
mkdir -p /rails/tmp/assets_between_runs/vite /rails/public/vite && rsync -a /rails/tmp/assets_between_runs/vite/. /rails/public/vite/. && \
mkdir -p /rails/tmp/assets_between_runs/assets /rails/public/assets && rsync -a /rails/tmp/assets_between_runs/assets/. /rails/public/assets/. && \
SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile && \
rsync -a /rails/public/vite/. /rails/tmp/assets_between_runs/vite/. && \
rsync -a /rails/public/assets/. /rails/tmp/assets_between_runs/assets/.
# Final stage for app image
FROM base as app
# Install packages needed for deployment
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=tmpfs,target=/var/log \
apt-get update -qq && \
apt-get install --no-install-recommends -y $RUNTIME_DEPS cron
# This maybe not needed for normal apps: I need Google Chrome for some scraping stuff.
#RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
# --mount=type=cache,target=/var/lib/apt,sharing=locked \
# --mount=type=tmpfs,target=/var/log \
# curl -sL https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
# echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list && \
# echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list && \
# apt-get update -qq && \
# apt-get install --no-install-recommends -y google-chrome-stable
# 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 --home /rails --shell /bin/bash && \
chown -R rails:rails db log 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"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment