Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DEMO.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ docker buildx build . -t rails-demo
docker run -p 3000:3000 -e RAILS_MASTER_KEY=$(cat config/master.key) --rm rails-demo
```

# Demo 5 - Bunding Javascript (esbuild)
# Demo 5 - Bundling Javascript (esbuild)

While optional, bundling Javascript is a popular choice, and starting with
Rails 7 there are three options: esbuild, rollup, and webpack. The
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ different contents. If both are specified, `--force` takes precedence.

* `--alpine` - use [alpine](https://www.alpinelinux.org/) as base image (requires [Alpine <= 3.18 OR Rails >= 8.0](https://github.com/sparklemotion/sqlite3-ruby/issues/434))
* `--fullstaq` - use [fullstaq](https://fullstaqruby.org/) [images](https://github.com/evilmartians/fullstaq-ruby-docker) on [quay.io](https://quay.io/repository/evl.ms/fullstaq-ruby?tab=tags&tag=latest)
* `--hardened` - use `dhi.io/ruby:$RUBY_VERSION-dev` as base image (mutually exclusive with `--alpine` or `--fullstaq`)
* `--jemalloc` - use [jemalloc](https://jemalloc.net/) memory allocator
* `--swap=n` - allocate swap space. See [falloc options](https://man7.org/linux/man-pages/man1/fallocate.1.html#OPTIONS) for suffixes
* `--yjit` - enable [YJIT](https://github.com/ruby/ruby/blob/master/doc/yjit/yjit.md) optimizing compiler
Expand All @@ -50,7 +51,7 @@ different contents. If both are specified, `--force` takes precedence.

* `--ci` - include test gems in deployed image
* `--compose` - generate a `docker-compose.yml` file
* `--max-idle=n` - exit afer *n* seconds of inactivity. Supports [iso 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) and [sleep](https://man7.org/linux/man-pages/man1/sleep.1.html#DESCRIPTION) syntaxes. Uses passenger for now, awaiting [puma](https://github.com/puma/puma/issues/2580) support.
* `--max-idle=n` - exit after *n* seconds of inactivity. Supports [iso 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) and [sleep](https://man7.org/linux/man-pages/man1/sleep.1.html#DESCRIPTION) syntaxes. Uses passenger for now, awaiting [puma](https://github.com/puma/puma/issues/2580) support.
* `--nginx` - serve static files via [nginx](https://www.nginx.com/). May require `--root` on some targets to access `/dev/stdout`
* `--thruster` - serve static files via [thruster](https://github.com/basecamp/thruster?tab=readme-ov-file#thruster).
* `--link` - add [--link](https://docs.docker.com/engine/reference/builder/#copy---link) to COPY statements. Some tools (like at the moment, [buildah](https://www.redhat.com/en/topics/containers/what-is-buildah)) don't yet support this feature.
Expand Down
8 changes: 8 additions & 0 deletions lib/generators/dockerfile_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class DockerfileGenerator < Rails::Generators::Base
"compose" => false,
"fullstaq" => false,
"gemfile-updates" => true,
"hardened" => false,
"jemalloc" => true,
"label" => {},
"link" => false,
Expand Down Expand Up @@ -200,6 +201,9 @@ class DockerfileGenerator < Rails::Generators::Base
class_option :fullstaq, type: :boolean, default: OPTION_DEFAULTS.fullstaq,
descr: "use Fullstaq Ruby image from Quay.io"

class_option :hardened, type: :boolean, default: OPTION_DEFAULTS.hardened,
desc: "use hardened Ruby image from dhi.io"

class_option :yjit, type: :boolean, default: OPTION_DEFAULTS.yjit,
desc: "enable YJIT optimizing compiler"

Expand Down Expand Up @@ -294,6 +298,10 @@ class DockerfileGenerator < Rails::Generators::Base
def generate_app
source_paths.push File.expand_path("./templates", __dir__)

if options.hardened? && (options.fullstaq? || options.alpine?)
raise Thor::Error, "--hardened is mutually exclusive with --fullstaq and --alpine"
end

# merge options
options.label.replace(@@labels.merge(options.label).select { |key, value| value != "" })

Expand Down
2 changes: 2 additions & 0 deletions lib/generators/templates/Dockerfile.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ ARG RUBY_VERSION=<%= RUBY_VERSION %>
<% end -%>
<% if options.fullstaq -%>
FROM <%= platform %>quay.io/evl.ms/fullstaq-ruby:${RUBY_VERSION}-<%= options.jemalloc ? 'jemalloc-' : 'malloctrim-' %><%= variant %><% unless options.precompile == "defer" %> AS base<% end %>
<% elsif options.hardened -%>
FROM <%= platform %>dhi.io/ruby:$RUBY_VERSION-dev<% unless options.precompile == "defer" %> AS base<% end %>
<% else -%>
FROM <%= platform %><%= options.registry %>ruby:$RUBY_VERSION-<%= variant %><% unless options.precompile == "defer" %> AS base<% end %>
<% end -%>
Expand Down
6 changes: 3 additions & 3 deletions test/results/alpine/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ RUN gem update --system --no-document && \
gem install -N bundler

# Install base packages
RUN apk add --no-cache curl jemalloc postgresql-client tzdata
RUN apk add --no-cache curl jemalloc postgresql-client tzdata vips

# Set production environment
ENV BUNDLE_DEPLOYMENT="1" \
Expand All @@ -32,7 +32,7 @@ ENV BUNDLE_DEPLOYMENT="1" \
FROM base AS build

# Install packages needed to build gems and node modules
RUN apk add --no-cache build-base gyp libpq-dev pkgconfig python3 yaml-dev
RUN apk add --no-cache build-base gyp libffi-dev libpq-dev pkgconfig python3 yaml-dev

# Install JavaScript dependencies
ARG NODE_VERSION=xxx
Expand Down Expand Up @@ -68,7 +68,7 @@ RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
FROM base

# Install packages needed for deployment
RUN apk add --no-cache libpq
RUN apk add --no-cache imagemagick libpq vips

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
Expand Down
8 changes: 6 additions & 2 deletions test/results/api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ RUN gem update --system --no-document && \

# Install base packages
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libjemalloc2 sqlite3 && \
apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
Expand All @@ -52,7 +52,7 @@ FROM base AS build

# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential libyaml-dev pkg-config && \
apt-get install --no-install-recommends -y build-essential libffi-dev libyaml-dev pkg-config && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install application gems
Expand All @@ -71,6 +71,10 @@ RUN bundle exec bootsnap precompile app/ lib/
# Final stage for app image
FROM base

# Install packages needed for deployment
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y imagemagick libvips && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
Expand Down
8 changes: 6 additions & 2 deletions test/results/bun/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN gem update --system --no-document && \

# Install base packages
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libjemalloc2 sqlite3 && \
apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
Expand All @@ -35,7 +35,7 @@ FROM base AS build

# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential libyaml-dev pkg-config unzip && \
apt-get install --no-install-recommends -y build-essential libffi-dev libyaml-dev pkg-config unzip && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install Bun
Expand Down Expand Up @@ -67,6 +67,10 @@ 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 imagemagick libvips && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
Expand Down
9 changes: 7 additions & 2 deletions test/results/cache/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ RUN gem update --system --no-document && \
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 curl libjemalloc2 sqlite3
apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3

# Set production environment
ENV BUNDLE_DEPLOYMENT="1" \
Expand All @@ -38,7 +38,7 @@ FROM base AS build
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-essential libyaml-dev node-gyp pkg-config python-is-python3
apt-get install --no-install-recommends -y build-essential libffi-dev libyaml-dev node-gyp pkg-config python-is-python3

# Install JavaScript dependencies
ARG NODE_VERSION=xxx
Expand Down Expand Up @@ -79,6 +79,11 @@ RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
# Final stage for app image
FROM base

# Install packages needed for deployment
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 imagemagick libvips

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
Expand Down
8 changes: 6 additions & 2 deletions test/results/esbuild/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN gem update --system --no-document && \

# Install base packages
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libjemalloc2 sqlite3 && \
apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
Expand All @@ -35,7 +35,7 @@ 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 libyaml-dev node-gyp pkg-config python-is-python3 && \
apt-get install --no-install-recommends -y build-essential libffi-dev libyaml-dev node-gyp pkg-config python-is-python3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install JavaScript dependencies
Expand Down Expand Up @@ -70,6 +70,10 @@ 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 imagemagick libvips && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
Expand Down
8 changes: 6 additions & 2 deletions test/results/execjs_importmap/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN gem update --system --no-document && \

# Install base packages needed to install nodejs
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libjemalloc2 sqlite3 && \
apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
Expand All @@ -42,7 +42,7 @@ FROM base AS build

# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential libyaml-dev pkg-config && \
apt-get install --no-install-recommends -y build-essential libffi-dev libyaml-dev pkg-config && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Build options
Expand All @@ -67,6 +67,10 @@ 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 imagemagick libvips && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
Expand Down
8 changes: 6 additions & 2 deletions test/results/execjs_node/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN gem update --system --no-document && \

# Install base packages needed to install nodejs
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libjemalloc2 sqlite3 && \
apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
Expand All @@ -42,7 +42,7 @@ 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 libyaml-dev node-gyp pkg-config python-is-python3 && \
apt-get install --no-install-recommends -y build-essential libffi-dev libyaml-dev node-gyp pkg-config python-is-python3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install yarn
Expand Down Expand Up @@ -75,6 +75,10 @@ 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 imagemagick libvips && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
Expand Down
71 changes: 71 additions & 0 deletions test/results/hardened/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# syntax=docker/dockerfile:1
# check=error=true

# Make sure RUBY_VERSION matches the Ruby version in .ruby-version
ARG RUBY_VERSION=xxx
FROM dhi.io/ruby:$RUBY_VERSION-dev AS base

# Rails app lives here
WORKDIR /rails

# Update gems and bundler
RUN gem update --system --no-document && \
gem install -N bundler

# Install base packages
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libjemalloc2 sqlite3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
ENV BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development:test" \
RAILS_ENV="production"


# 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 libyaml-dev pkg-config && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install application gems
COPY Gemfile Gemfile.lock ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git

# Copy application code
COPY . .

# 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


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

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

# Deployment options
ENV DATABASE_URL="sqlite3:///data/production.sqlite3"

# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]

# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
VOLUME /data
CMD ["./bin/rails", "server"]
6 changes: 3 additions & 3 deletions test/results/litefs/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN gem update --system --no-document && \

# Install base packages
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libjemalloc2 sqlite3 && \
apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
Expand All @@ -35,7 +35,7 @@ FROM base AS build

# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential libyaml-dev pkg-config && \
apt-get install --no-install-recommends -y build-essential libffi-dev libyaml-dev pkg-config && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install application gems
Expand Down Expand Up @@ -63,7 +63,7 @@ COPY config/litefs.yml /etc/litefs.yml

# Install packages needed for deployment
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y ca-certificates fuse3 sudo && \
apt-get install --no-install-recommends -y ca-certificates fuse3 imagemagick libvips sudo && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Copy built artifacts: gems, application
Expand Down
8 changes: 6 additions & 2 deletions test/results/litestream/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN gem update --system --no-document && \

# Install base packages
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libjemalloc2 sqlite3 && \
apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
Expand All @@ -35,7 +35,7 @@ FROM base AS build

# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential libyaml-dev pkg-config && \
apt-get install --no-install-recommends -y build-essential libffi-dev libyaml-dev pkg-config && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install application gems
Expand All @@ -57,6 +57,10 @@ 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 imagemagick libvips && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

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