# syntax=docker/dockerfile:1 # check=error=true ARG RUBY_VERSION=3.3.6 ARG RUBY_ABI_VERSION=3.3.0 ARG NODE_VERSION=22 FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base WORKDIR /rails RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ apt-get update -qq && \ apt-get install --no-install-recommends -y curl libjemalloc2 libvips postgresql-client ENV RAILS_ENV="production" \ BUNDLE_DEPLOYMENT="1" \ BUNDLE_PATH="/usr/local/bundle" \ BUNDLE_WITHOUT="development:test" # ============================================================================== # Throw-away build stage to reduce size of final image # ============================================================================== ARG RUBY_ABI_VERSION ARG NODE_VERSION FROM base AS build RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ --mount=type=cache,target=/root/.npm \ apt-get update -qq && \ curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - && \ apt-get install --no-install-recommends -y build-essential git libpq-dev libyaml-dev pkg-config nodejs && \ npm install -g yarn # Gems: cache downloaded .gem files separately from extracted gems. # The cache mount target matches the bundler download cache for the Ruby ABI version. COPY Gemfile Gemfile.lock ./ RUN --mount=type=cache,id=bundler,target=/usr/local/bundle/ruby/${RUBY_ABI_VERSION}/cache \ bundle install && \ rm -rf "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \ bundle exec bootsnap precompile --gemfile # Node modules: cache yarn downloads independently of app code. # .npmrc is injected via secret at build time — no need to COPY it. COPY package.json yarn.lock ./ RUN --mount=type=cache,id=yarn,target=/yarn-cache \ --mount=type=secret,id=npmrc,target=/rails/.npmrc \ yarn install --frozen-lockfile --cache-folder /yarn-cache COPY . . RUN bundle exec bootsnap precompile app/ lib/ RUN ./bin/vite build RUN rm -rf node_modules tmp/cache vendor/javascript spec test # ============================================================================== # Final stage for app image # ============================================================================== FROM base COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" COPY --from=build /rails /rails RUN groupadd --system --gid 1000 rails && \ useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \ chown -R rails:rails db log storage tmp USER 1000:1000 ENTRYPOINT ["/rails/bin/docker-entrypoint.prod.sh"] EXPOSE 3000 CMD ["./bin/rails", "server", "-b", "0.0.0.0", "-p", "3000"]