# syntax=docker/dockerfile:1 # check=error=true
# This Dockerfile is designed for production, not development. Use with Kamal or build’n’run by hand: # docker build -t <%= app_name %> . # docker run -d -p 80:<%= skip_thruster? ? 3000 : 80 %> -e RAILS_MASTER_KEY=<value from config/master.key> –name <%= app_name %> <%= app_name %>
# For a containerized dev environment, see Dev Containers: guides.rubyonrails.org/getting_started_with_devcontainer.html
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version ARG RUBY_VERSION=<%= Gem.ruby_version %> FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
# Rails app lives here WORKDIR /rails
# Install base packages RUN apt-get update -qq && \
apt-get install --no-install-recommends -y <%= dockerfile_base_packages.join(" ") %> && \
ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
# Set production environment variables and enable jemalloc for reduced memory usage and latency. ENV RAILS_ENV=“production” \
BUNDLE_DEPLOYMENT="1" \ BUNDLE_PATH="/usr/local/bundle" \ BUNDLE_WITHOUT="development" \ LD_PRELOAD="/usr/local/lib/libjemalloc.so"
# Throw-away build stage to reduce size of final image FROM base AS build
# Install packages needed to build gems<%= (using_node? || using_bun?) ? “ and node modules” : “” %> RUN apt-get update -qq && \
apt-get install --no-install-recommends -y <%= dockerfile_build_packages.join(" ") %> && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
<% if using_node? -%> # Install JavaScript dependencies ARG NODE_VERSION=<%= node_version %> ARG YARN_VERSION=<%= dockerfile_yarn_version %> ENV PATH=/usr/local/node/bin:$PATH <% if yarn_through_corepack? -%> RUN curl -sL 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 && \
rm -rf /tmp/node-build-master
RUN corepack enable && yarn set version $YARN_VERSION <% else -%> RUN curl -sL 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
<% end -%>
<% end -%> <% if using_bun? -%> ENV BUN_INSTALL=/usr/local/bun ENV PATH=/usr/local/bun/bin:$PATH ARG BUN_VERSION=<%= dockerfile_bun_version %> RUN curl -fsSL bun.sh/install | bash -s – “bun-v${BUN_VERSION}”
<% end -%> # Install application gems COPY vendor/* ./vendor/ COPY Gemfile Gemfile.lock ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git<% if depend_on_bootsnap? -%> && \
# -j 1 disable parallel compilation to avoid a QEMU bug: https://github.com/rails/bootsnap/issues/495
bundle exec bootsnap precompile -j 1 --gemfile<% end %>
<% if using_node? -%> # Install node modules COPY package.json yarn.lock ./ RUN yarn install –immutable
<% end -%> <% if using_bun? -%> # Install node modules COPY package.json bun.lock* ./ RUN bun install –frozen-lockfile
<% end -%> # Copy application code COPY . .
<% if depend_on_bootsnap? -%> # Precompile bootsnap code for faster boot times. # -j 1 disable parallel compilation to avoid a QEMU bug: github.com/rails/bootsnap/issues/495 RUN bundle exec bootsnap precompile -j 1 app/ lib/
<% end -%> <% unless dockerfile_binfile_fixups.empty? -%> # Adjust binfiles to be executable on Linux <%= “RUN ” + dockerfile_binfile_fixups.join(“ && \n ”) %>
<% end -%> <% unless options.api? || skip_asset_pipeline? -%> # Precompiling assets for production without requiring secret RAILS_MASTER_KEY RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
<% end -%>
<% if using_node? || using_bun? -%> RUN rm -rf node_modules <% end %>
# Final stage for app image FROM base
# 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
USER 1000:1000
# Copy built artifacts: gems, application COPY –chown=rails:rails –from=build “${BUNDLE_PATH}” “${BUNDLE_PATH}” COPY –chown=rails:rails –from=build /rails /rails
# Entrypoint prepares the database. ENTRYPOINT [“/rails/bin/docker-entrypoint”]
<% if skip_thruster? -%> # Start the server by default, this can be overwritten at runtime EXPOSE 3000 CMD [“./bin/rails”, “server”] <% else -%> # Start server via Thruster by default, this can be overwritten at runtime EXPOSE 80 CMD [“./bin/thrust”, “./bin/rails”, “server”] <% end -%>