diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..0e34b06d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +.git +tmp +!tmp/pids +log +public/assets +public/packs +.bundle + +db/*.sqlite3 +db/*.sqlite3-* + +storage +config/master.key +config/credentials/*.key + +node_modules diff --git a/Dockerfile b/Dockerfile new file mode 100755 index 00000000..bacc759c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,133 @@ +# syntax = docker/dockerfile:experimental + +# Dockerfile used to build a deployable image for a Rails application. +# Adjust as required. +# +# Common adjustments you may need to make over time: +# * Modify version numbers for Ruby, Bundler, and other products. +# * Add library packages needed at build time for your gems, node modules. +# * Add deployment packages needed by your application +# * Add (often fake) secrets needed to compile your assets + +####################################################################### + +# Learn more about the chosen Ruby stack, Fullstaq Ruby, here: +# https://github.com/evilmartians/fullstaq-ruby-docker. +# +# We recommend using the highest patch level for better security and +# performance. + +ARG RUBY_VERSION=2.7.5 +ARG VARIANT=jemalloc-slim +FROM quay.io/evl.ms/fullstaq-ruby:${RUBY_VERSION}-${VARIANT} as base + +ARG NODE_VERSION=16.17.0 +ARG BUNDLER_VERSION=2.3.19 + +ARG RAILS_ENV=production +ENV RAILS_ENV=${RAILS_ENV} + +ENV RAILS_SERVE_STATIC_FILES true +ENV RAILS_LOG_TO_STDOUT true + +ARG BUNDLE_WITHOUT=development:test +ARG BUNDLE_PATH=vendor/bundle +ENV BUNDLE_PATH ${BUNDLE_PATH} +ENV BUNDLE_WITHOUT ${BUNDLE_WITHOUT} + +RUN mkdir /app +WORKDIR /app +RUN mkdir -p tmp/pids + +RUN curl https://get.volta.sh | bash +ENV VOLTA_HOME /root/.volta +ENV PATH $VOLTA_HOME/bin:/usr/local/bin:$PATH +RUN volta install node@${NODE_VERSION} + +####################################################################### + +# install packages only needed at build time + +FROM base as build_deps + +ARG BUILD_PACKAGES="git build-essential libpq-dev wget vim curl gzip xz-utils libsqlite3-dev" +ENV BUILD_PACKAGES ${BUILD_PACKAGES} + +RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \ + --mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \ + apt-get update -qq && \ + apt-get install --no-install-recommends -y ${BUILD_PACKAGES} \ + && rm -rf /var/lib/apt/lists /var/cache/apt/archives + +####################################################################### + +# install gems + +FROM build_deps as gems + +RUN gem update --system --no-document && \ + gem install -N bundler -v ${BUNDLER_VERSION} + +COPY Gemfile* ./ +RUN bundle install && rm -rf vendor/bundle/ruby/*/cache + +####################################################################### + +# install node modules + +FROM build_deps as node_modules + +COPY package*json ./ +COPY yarn.* ./ +RUN volta install yarn && yarn install; + +####################################################################### + +# install deployment packages + +FROM base + +ARG DEPLOY_PACKAGES="postgresql-client file vim curl gzip libsqlite3-0" +ENV DEPLOY_PACKAGES=${DEPLOY_PACKAGES} + +RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \ + --mount=type=cache,id=prod-apt-lib,sharing=locked,target=/var/lib/apt \ + apt-get update -qq && \ + apt-get install --no-install-recommends -y \ + ${DEPLOY_PACKAGES} \ + && rm -rf /var/lib/apt/lists /var/cache/apt/archives + +# copy installed gems +COPY --from=gems /app /app +COPY --from=gems /usr/lib/fullstaq-ruby/versions /usr/lib/fullstaq-ruby/versions +COPY --from=gems /usr/local/bundle /usr/local/bundle + +# copy installed node modules +COPY --from=node_modules /app/node_modules /app/node_modules + +####################################################################### + +# Deploy your application +COPY . . + +# Adjust binstubs to run on Linux and set current working directory +RUN chmod +x /app/bin/* && \ + sed -i 's/ruby.exe/ruby/' /app/bin/* && \ + sed -i '/^#!/aDir.chdir File.expand_path("..", __dir__)' /app/bin/* + +# The following enable assets to precompile on the build server. Adjust +# as necessary. If no combination works for you, see: +# https://fly.io/docs/rails/getting-started/existing/#access-to-environment-variables-at-build-time +ENV SECRET_KEY_BASE 1 +# ENV AWS_ACCESS_KEY_ID=1 +# ENV AWS_SECRET_ACCESS_KEY=1 + +# Run build task defined in lib/tasks/fly.rake +ARG BUILD_COMMAND="bin/rails fly:build" +RUN ${BUILD_COMMAND} + +# Default server start instructions. Generally Overridden by fly.toml. +ENV PORT 8080 +ARG SERVER_COMMAND="bin/rails fly:server" +ENV SERVER_COMMAND ${SERVER_COMMAND} +CMD ${SERVER_COMMAND} diff --git a/fly.toml b/fly.toml new file mode 100644 index 00000000..f5ff2424 --- /dev/null +++ b/fly.toml @@ -0,0 +1,51 @@ +# fly.toml file generated for swedishbirds on 2022-09-19T09:29:47+02:00 + +app = "swedishbirds" +kill_signal = "SIGINT" +kill_timeout = 5 +processes = [] + +[build] + [build.args] + BUILD_COMMAND = "bin/rails fly:build" + SERVER_COMMAND = "bin/rails fly:server" + +[deploy] + release_command = "bin/rails fly:release" + +[env] + PORT = "8080" + +[experimental] + allowed_public_ports = [] + auto_rollback = true + +[[services]] + http_checks = [] + internal_port = 8080 + processes = ["app"] + protocol = "tcp" + script_checks = [] + [services.concurrency] + hard_limit = 25 + soft_limit = 20 + type = "connections" + + [[services.ports]] + force_https = true + handlers = ["http"] + port = 80 + + [[services.ports]] + handlers = ["tls", "http"] + port = 443 + + [[services.tcp_checks]] + grace_period = "1s" + interval = "15s" + restart_limit = 0 + timeout = "2s" + +[[statics]] + guest_path = "/app/public" + url_prefix = "/" diff --git a/lib/tasks/fly.rake b/lib/tasks/fly.rake new file mode 100644 index 00000000..454c7002 --- /dev/null +++ b/lib/tasks/fly.rake @@ -0,0 +1,23 @@ +# commands used to deploy a Rails application +namespace :fly do + # BUILD step: + # - changes to the filesystem made here DO get deployed + # - NO access to secrets, volumes, databases + # - Failures here prevent deployment + task :build => 'assets:precompile' + + # RELEASE step: + # - changes to the filesystem made here are DISCARDED + # - full access to secrets, databases + # - failures here prevent deployment + task :release => 'db:migrate' + + # SERVER step: + # - changes to the filesystem made here are deployed + # - full access to secrets, databases + # - failures here result in VM being stated, shutdown, and rolled back + # to last successful deploy (if any). + task :server do + sh 'bin/rails server' + end +end