Detection

migetpacks detects Ruby when any of these files are present in your project root:
  • Gemfile
  • Rakefile
  • config.ru

Version Detection

Ruby version is resolved in this order:
PrioritySourceExample
1RUBY_VERSION env varRUBY_VERSION=3.3
2.ruby-version file3.4.4
3ruby declaration in Gemfileruby "3.3.0"
4Default3.4.4
The ruby- prefix is automatically stripped (e.g., ruby-3.2.0 becomes 3.2.0).

Build Process

migetpacks generates a multi-stage Dockerfile with bundler layer caching:
# Builder stage
FROM ruby:3.4 AS builder
WORKDIR /build

# Layer 1: Copy Gemfile for layer caching
COPY Gemfile Gemfile.lock ./

# Layer 2: Configure and install gems (CACHED when Gemfile unchanged)
ENV GEM_HOME=/build/vendor/bundle
ENV BUNDLE_PATH=/build/vendor/bundle
RUN gem install bundler -v '2.5.0' --no-document && \
    bundle config set --local path '/build/vendor/bundle' && \
    bundle config set --local deployment 'true' && \
    bundle install --jobs 4 --retry 3

# Layer 3: Copy source code
COPY . .

# Layer 4: Rails asset precompilation and cleanup
ENV RAILS_ENV=production
ENV SECRET_KEY_BASE_DUMMY=1
RUN bundle exec rake assets:precompile && \
    bundle exec rake assets:clean && \
    rm -rf .git test spec vendor/bundle/ruby/*/cache

# Runtime stage
FROM ruby:3.4-slim
RUN apt-get update && apt-get install -y libpq5 tzdata ca-certificates
WORKDIR /app
COPY --from=builder /build /app

Dependency Detection

migetpacks inspects your Gemfile and Gemfile.lock to install the correct system libraries:
GemBuild PackageRuntime Package
pglibpq-devlibpq5
mysql2, trilogylibmariadb-devlibmariadb3
sqlite3libsqlite3-devlibsqlite3-0
nokogiri, railslibxml2-dev, libxslt1-devlibxml2, libxslt1.1
Additionally, tzdata and ca-certificates are always installed in the runtime image.

Bundler Version

The bundler version is automatically detected from Gemfile.lock (the BUNDLED WITH section) and installed in the builder stage.

Local Gems

If your Gemfile references local gems with path: options, those directories are automatically copied before bundle install to ensure they are available during gem resolution.

Rails Asset Precompilation

If your project has a Rakefile and either app/assets/ or app/javascript/ directories, migetpacks automatically:
  1. Sets RAILS_ENV=production, SECRET_KEY_BASE_DUMMY=1, and a dummy DATABASE_URL
  2. Runs bundle exec rake assets:precompile
  3. Runs bundle exec rake assets:clean

Runtime Cleanup

The following are removed from the final image:
  • .git/, .github/
  • test/, tests/, spec/, features/
  • .rspec, .rubocop*
  • vendor/bundle/ruby/*/cache/

Run Command

The default run command is determined in this order:
PrioritySourceCommand
1RUN_COMMAND env varUser-specified
2web: in ProcfileFrom Procfile
3config.ru existsbundle exec puma -C config/puma.rb
4Defaultbundle exec ruby app.rb

Runtime Environment

The following environment variables are set in the runtime container:
RAILS_ENV=production
RACK_ENV=production
RAILS_SERVE_STATIC_FILES=enabled
RAILS_LOG_TO_STDOUT=enabled
MALLOC_ARENA_MAX=2
DISABLE_SPRING=1
PUMA_PERSISTENT_TIMEOUT=95

Caching

Docker Layer Caching

Gems are installed in a separate layer before source code is copied. bundle install is only re-run when Gemfile or Gemfile.lock changes.

BuildKit Cache Mounts

When BUILD_CACHE_DIR is configured, BuildKit cache mounts are used:
Cache PathContents
/cache/bundlerBundler gem cache

Registry Cache

Use CACHE_IMAGE to push/pull BuildKit inline cache layers to a registry for cross-build caching.

DHI Support

Ruby is fully supported with Docker Hardened Images.
StageImage
Builddhi.io/ruby:{version}-dev
Runtimedhi.io/ruby:{version}

DHI-Specific Behavior

The DHI runtime is distroless (no shell, no apt-get), which requires special handling: Native gem libraries are copied from the builder stage:
COPY --from=builder /usr/lib/*/libpq.so* /usr/lib/
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/ssl/certs /etc/ssl/certs
Process commands are transformed since shebangs do not work in distroless:
  • ./bin/rails server becomes ruby bin/rails server
  • bundle exec commands work because bundler is installed as a gem
BUNDLER_VERSION is explicitly set in the environment to prevent bundler from attempting auto-switching (which fails without /usr/bin/env).
Shell-dependent features like .profile.d scripts and shell variable expansion (${PORT:-5000}) are not available in DHI runtime images. Use environment variables directly.

Multi-Buildpack

Ruby applications commonly use Node.js for asset compilation. When package.json is detected alongside a Ruby project, Node.js is automatically added as a secondary buildpack:
# Explicit buildpack ordering
docker run --rm \
  -v /path/to/app:/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-rails-app:latest \
  -e BUILDPACKS=ruby,nodejs \
  miget/migetpacks:latest
See the Multi-Buildpack guide for more details.

Example

docker run --rm \
  -v /path/to/app:/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-ruby-app:latest \
  miget/migetpacks:latest

With Custom Options

docker run --rm \
  -v /path/to/app:/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=registry.io/app:v1 \
  -e RUBY_VERSION=3.3 \
  -e RAILS_MASTER_KEY=abc123 \
  -e BUNDLE_WITHOUT="development test" \
  -e USE_DHI=true \
  miget/migetpacks:latest