[Proposal] Reduce docker image size by deleting gem useless files (tests, *.o, *.c)

Overview

We could reduce the size of the image the generated Dockerfile produces by omitting useless gem files.

By default, the generated Dockerfile includes files that are not going to be needed in production:

  • gem .c and .o files
  • gem along tests and test data.

This is a waste of space. We can shave off some megabytes by deleting them.

Example

Create a new rails project and build it’s docker image (using the generated Dockerfile):

> rails new blog 
> docker build -t image1 .
> docker images image1
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
image1       latest    3123093e3c64   6 hours ago   566MB

If we update the generated Dockerfile from:

RUN bundle install && \
    rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
    bundle exec bootsnap precompile --gemfile

to

RUN bundle install && \
    rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
    # remove unneeded files (cached *.gem, *.o, *.c) (as per https://ledermann.dev/blog/2018/04/19/dockerize-rails-the-lean-way/)
    find "${BUNDLE_PATH}"/ruby/3.3.0/gems/ -name "*.c" -delete && \
    find "${BUNDLE_PATH}"/ruby/3.3.0/gems/ -name "*.o" -delete && \
    # delete the test and spec directories from all the gems
    find "${BUNDLE_PATH}"/ruby/3.3.0/gems/ -mindepth 2 -maxdepth 2 -type d \( -name spec -o -name test \) -exec rm -rf {} + && \
    bundle exec bootsnap precompile --gemfile
> docker images image2
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
image2       latest    2974a492e5c3   19 seconds ago   563MB

This reduces the image size by 3Mb. It’s not much, but it will increase as more dependencies with more tests are introduces. Some dependencies may have fixtures and test files that could increase the size by a lot.

If others feel it’s a good tradeoff (added complexity vs reduced docker image size), I could open a PR for review, or an issue over at Github.

System configuration

Rails version: 8.0.1

Ruby version: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin24]