Giter Club home page Giter Club logo

docker-rails-base's Introduction

Build images

DockerRailsBase

Building Docker images usually takes a long time. This repo contains base images with preinstalled dependencies for Ruby on Rails, so building a production image will be 2-3 times faster.

What?

When using the official Ruby image, building a Docker image for a typical Rails application requires lots of time for installing dependencies - mainly OS packages, Ruby gems, Ruby gems with native extensions (Nokogiri etc.) and Node modules. This is required every time the app needs to be deployed to production.

I was looking for a way to reduce this time, so I created base images that contain most of the dependencies used in my applications.

And while I'm at it, I also moved as much as possible from the app-specific Dockerfile into the base image by using ONBUILD triggers. This makes the Dockerfile in my apps small and simple.

Performance

I compared building times using a typical Rails application. This is the result on my local machine:

  • Based on official Ruby image: 4:50 min
  • Based on DockerRailsBase: 1:57 min

As you can see, using DockerRailsBase is more than 2 times faster compared to the official Ruby image. It saves nearly 3min on every build.

Note: Before I started timing, the base image was not available on my machine, so it was downloaded first, which took some time. If the base image is already available, the building time is only 1:18min (3 times faster).

How?

This repo is based on the following assumptions:

To build a very small production image, multi-stage building is used. There are two Dockerfiles in this repo, one for the first stage (called "Builder") and one for the resulting stage (called "Final").

Builder stage

Used for installing Ruby gems and Node modules. Includes Git, Node.js and some build tools - all we need to compile assets.

  • Based on ruby:2.7.1-alpine
  • Adds packages needed for installing gems and compiling assets: Git, Node.js, Yarn, PostgreSQL client and build tools
  • Adds some standard Ruby gems (Rails 6 etc., see Gemfile)
  • Adds some standard Node modules (Vue.js etc., see package.json)
  • Via ONBUILD triggers it installs missing gems and Node modules, then compiles the assets

See Builder/Dockerfile

Final stage

Used to build the production image which includes just the minimum.

  • Based on ruby:2.7.1-alpine
  • Adds packages needed for production: postgresql-client, tzdata, file
  • Via ONBUILD triggers it mainly copies the app and gems from the "Builder" stage

See Final/Dockerfile

Staying up-to-date

Using Dependabot, every updated Ruby gem or Node module results in an updated image.

Usage example

FROM ledermann/rails-base-builder:latest AS Builder
FROM ledermann/rails-base-final:latest
USER app
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]

Yes, this is the complete Dockerfile of the Rails app. It's so simple because the work is done by ONBUILD triggers.

FAQ

Why not simply use layer caching?

Docker supports layer caching, so for building images it performs just the needed steps: If there is a layer from a former build and nothing has changed, it will be used. But for dependencies, this means: If a single Ruby gem in the application was updated or added, the step with bundle install is run again, so all gems will be installed again.

Using a prebuilt image improves installing dependencies a lot, because only the different/updated dependencies will be installed - all existing ones will be reused.

What if my app requires slightly different dependencies?

This doesn't matter:

  • A missing Alpine package can be installed with apk add inside your app's Dockerfile.
  • A missing Node module (or version) will be installed with rails assets:precompile via the ONBUILD trigger.
  • A missing Ruby gem (or version) will be installed with bundle install via the ONBUILD trigger.

There are gems included that my app doesn't need. Will they bloat the resulting image?

No. In the build stage there is a bundle clean --force, which uninstalls all gems not referenced in the app's Gemfile.

docker-rails-base's People

Contributors

dependabot-preview[bot] avatar ledermann avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.