Skip to content

Commit

Permalink
Deploy using Dockerfile instead of buildpack
Browse files Browse the repository at this point in the history
Somewhat based on the Dockfile template in Rails:
https://github.com/rails/rails/blob/4f0f3448cde85ff3d1485366231650258ea62b71/railties/lib/rails/generators/rails/app/templates/Dockerfile.tt

Needed after heroku/heroku-buildpack-ruby#1428
because deploys failed like this:

    ...
    Machine started in 390ms
    Activating bundler (>= 0.a) failed:
    Permission denied @ rb_sysopen - /workspace/vendor/bundle/ruby/3.2.0/specifications/bundler-2.5.6.gemspec
    To install the version of bundler this project requires, run `gem install bundler -v '>= 0.a'`
  • Loading branch information
dentarg committed Mar 3, 2024
1 parent 8f3eaa5 commit a8534a5
Show file tree
Hide file tree
Showing 20 changed files with 185 additions and 43 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ on:
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-20.04
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./bin/docker-test
ruby:
runs-on: ubuntu-latest
env:
BUNDLE_LOCAL: 1
steps:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/deploy-fly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- run: |
echo "RUBY_VERSION=$(cat .ruby-version)" >> $GITHUB_ENV
- uses: dentarg/fly@main
with:
build-args: "RUBY_VERSION=${{ env.RUBY_VERSION }}"
fly-token: ${{ secrets.FLY_API_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
58 changes: 58 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
ARG RUBY_VERSION
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base

# The app lives here
WORKDIR /app

# Install base packages
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y \
curl \
postgresql-client

# Set production environment
ENV BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_CACHE_PATH="/usr/local/bundle/cache" \
BUNDLE_WITHOUT="development"

# Throw-away build stage to reduce size of final image
FROM base as build

# Install build packages
RUN apt-get install --no-install-recommends -y \
build-essential \
git \
libpq-dev \
pkg-config

# Install application gems
COPY Gemfile Gemfile.lock .ruby-version ./
COPY vendor/cache "${BUNDLE_CACHE_PATH}"
RUN bundle install --local

# Copy application code
COPY . .

# Final stage for app image
FROM base

ARG APPUSER=app
ARG APPDIR=/app

# Clean up installation packages to reduce image size
RUN rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
COPY --from=build $APPDIR $APPDIR

# Run and own only the runtime files as a non-root user for security
RUN mkdir -p log tmp
RUN groupadd --system --gid 1000 $APPUSER
RUN useradd $APPUSER --uid 1000 --gid 1000 --create-home --shell /bin/bash
RUN chown -R $APPUSER:$APPUSER log tmp
USER 1000:1000

# Start the server by default, this can be overwritten at runtime
CMD bin/start
8 changes: 2 additions & 6 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

source 'https://rubygems.org/'
ruby File.read('.ruby-version').chomp
ruby file: '.ruby-version'

gem 'sequel'
gem 'pg'
Expand All @@ -25,11 +25,7 @@ gem 'warning'
gem 'rake'
gem 'rubocop', '~> 1.60.2', require: false
gem 'dyno_metadata'

group :development do
gem 'overman'
gem 'localhost'
end
gem 'localhost'

group :test do
gem 'climate_control'
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ GEM
base64
faraday (>= 1, < 3)
sawyer (~> 0.9)
overman (0.87.3)
parallel (1.24.0)
parser (3.3.0.5)
ast (~> 2.4.1)
Expand Down Expand Up @@ -108,6 +107,7 @@ GEM
faraday (>= 0.17.3, < 3)
selma (0.2.2)
rb_sys (~> 0.9)
selma (0.2.2-aarch64-linux)
selma (0.2.2-arm64-darwin)
selma (0.2.2-x86_64-linux)
sentry-ruby (5.16.1)
Expand Down Expand Up @@ -147,6 +147,7 @@ GEM
zeitwerk (2.6.13)

PLATFORMS
aarch64-linux
arm64-darwin
ruby
x86_64-linux
Expand All @@ -164,7 +165,6 @@ DEPENDENCIES
m
minitest
octokit
overman
pg
puma
rack-flash3
Expand Down
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: bundle exec puma -C config/puma.rb
web: bundle exec puma --config config/puma.rb
11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ These instructions assume you are using OS X.
Install prerequisites

brew install postgresql
gem install overman
bundle install

Ruby gems are vendored into `vendor/cache`, you should always check in the gems when changing gems. The caching is set up with [`bundle package --all`](https://bundler.io/man/bundle-package.1.html).
Expand All @@ -24,13 +25,9 @@ Make sure PostgreSQL is running

postgres

Get a copy of the production database

rake db:pull

### Start the app

In production, the script `bin/web_start` ([background](https://github.com/Starkast/wikimum/commit/acf57ec06ddb9ff3403acf56ababaa58f8cd3f43)) is used, but we avoid using that in the `Procfile` because the integration tests reads that command and needs to get the PID of Puma, not the script, in order to cleanly shutdown Puma.
In production, the script `bin/start` is used, but we avoid using that in the `Procfile` because the integration tests reads that command and needs to get the PID of Puma, not the script, in order to cleanly shutdown Puma.

overman start

Expand Down Expand Up @@ -59,7 +56,7 @@ MAINTENANCE_MODE=true

### Console

foreman run bundle exec racksh
overman run bundle exec racksh

### Tests

Expand Down Expand Up @@ -90,7 +87,7 @@ GitHub Actions scan the code using [Brakeman](https://github.com/presidentbeef/b
If you need to ignore a weakness reported, update `config/brakeman.ignore`. You can get the JSON needed by running Brakeman like this:

```bash
docker run -it --rm -v $(pwd):/app -w /app ruby:2.7.6 bash
docker run -it --rm -v $(pwd):/app -w /app ruby:$(cat .ruby-version) bash
gem install brakeman
brakeman --force --format json .
```
Expand Down
15 changes: 0 additions & 15 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,6 @@ namespace(:test) do
end

namespace(:db) do
desc "Replace local database with production database"
task :pull do |t|
require "uri"
uri = URI.parse(ENV.fetch("DATABASE_URL", "postgres://localhost/wikimum"))
local_database = uri.path[1..-1]

trap("INT") { exit }

puts "Will remove local database '#{local_database}', press Enter to proceed, ^C to abort"
STDIN.gets

system "dropdb #{local_database}"
system "heroku pg:pull --app wikimum DATABASE_URL #{local_database}"
end

desc "Run migrations"
task :migrate, [:version] do |t, args|
require 'sequel'
Expand Down
8 changes: 8 additions & 0 deletions bin/docker-build
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

TAG=${TAG:-wikimum}

set -e
set -x

docker build . --build-arg RUBY_VERSION=$(cat .ruby-version) --tag $TAG "$@"
25 changes: 25 additions & 0 deletions bin/docker-reset-run
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

set -e
set -x

RUBY_VERSION=$(cat .ruby-version) docker compose up \
--build \
--always-recreate-deps \
--force-recreate \
--remove-orphans \
--renew-anon-volumes \
"$@"

# this script is useful if you run into some strange problem with the docker setup

# --always-recreate-deps Recreate dependent containers. Incompatible with --no-recreate.
# --force-recreate Recreate containers even if their configuration and image haven't changed.
# --remove-orphans Remove containers for services not defined in the Compose file.
#-V, --renew-anon-volumes Recreate anonymous volumes instead of retrieving data from the previous containers.

# these flags will make use of more disk space
# check and clean up with
#
# docker system df
# docker system prune
12 changes: 12 additions & 0 deletions bin/docker-run
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

set -e
set -x

RUBY_VERSION=$(cat .ruby-version) docker compose up \
--build \
"$@"

# useful but mutually exclusive flags
# --detach
# --exit-code-from app
24 changes: 24 additions & 0 deletions bin/docker-test
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash

set -x

RUBY_VERSION=$(cat .ruby-version) docker compose up \
--build \
--detach \
--wait

curl \
--verbose \
--silent \
--output /dev/null \
--fail-with-body \
--retry 5 \
--retry-all-errors \
--retry-connrefused \
127.0.0.1:8080

result=$?

docker compose stop

exit $result
1 change: 1 addition & 0 deletions bin/db_migrate → bin/start
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ set -e
set -u

bundle exec rake db:migrate
bundle exec puma --config config/puma.rb
6 changes: 0 additions & 6 deletions bin/web_start

This file was deleted.

1 change: 1 addition & 0 deletions default.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SESSION_SECRET=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
32 changes: 32 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: "3.9"
services:
app:
build:
context: .
args:
- RUBY_VERSION
ports:
- "127.0.0.1:8080:3000"
env_file:
- ./default.env
environment:
DATABASE_URL: postgres://postgres:postgres@db/db
PORT: 3000
depends_on:
db:
condition: service_healthy
db:
image: postgres
restart: always
# set shared memory limit when using docker-compose
# https://github.com/docker-library/postgres/issues/416
shm_size: 128mb
environment:
POSTGRES_DB: db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready --dbname=db --username=postgres"]
interval: 2s
retries: 10
start_period: 20s
7 changes: 3 additions & 4 deletions fly.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
app = "wikimum"

[build]
builder = "heroku/buildpacks:20"

[processes]
web = "/bin/sh -c 'bin/db_migrate && bin/web_start'"
# Dockerfile controls this
# https://community.fly.io/t/multiple-process-dockerfile/13639
web = ""

[env]
PRIMARY_REGION = "ams"
Expand Down
Binary file removed vendor/cache/overman-0.87.3.gem
Binary file not shown.
Binary file added vendor/cache/selma-0.2.2-aarch64-linux.gem
Binary file not shown.

0 comments on commit a8534a5

Please sign in to comment.