jonathanhefner / railbarge

Turn-key Docker base images for Rails apps

Home Page:https://hub.docker.com/u/railbarge

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

railbarge

railbarge is a set of Docker images that uses ONBUILD instructions plus dockhand to provide a turn-key Dockerfile UX for Rails applications.

For example, the following Dockerfile will work for many Rails applications:

ARG RUBY_VERSION=3.2.0

FROM railbarge/builder:ruby-$RUBY_VERSION as builder

FROM railbarge/app:ruby-$RUBY_VERSION
COPY --from=builder /artifacts /

It will:

  • Set RAILS_ENV to production, and set BUNDLE_ONLY based on RAILS_ENV in order to limit which packages and gems are installed (in both the builder and final application stages).

  • Install buildtime-only apt packages in the builder stage based on common gems in your Gemfile, such as libsqlite3-dev if using the sqlite3 gem or libpq-dev if using the pg gem.

  • Install gems as artifacts in the builder stage.

  • Install Node.js in the builder stage if your application has a .node-version file or a package.json file with an engines.node value.

  • Set NODE_ENV to production.

  • Install Node.js modules as artifacts in the builder stage if your application has a Yarn, NPM, or PNPM lock file.

  • Copy your application code as an artifact in the builder stage.

  • Precompile gem and application code with bootsnap if present.

  • Precompile assets with a dummy SECRET_KEY_BASE if your application uses the asset pipeline. To use the actual SECRET_KEY_BASE from your credentials file, set the RAILS_MASTER_KEY or config/master.key build secret:

    $ RAILS_MASTER_KEY="..." docker build --secret id=RAILS_MASTER_KEY -t my_cool_app .
    $ docker build --secret id=config/master.key -t my_cool_app .
    $ docker build --secret id=config/master.key,src=config/credentials/production.key -t my_cool_app .
  • Fix binstubs in your application's bin/ directory if they were generated on Windows.

  • Install runtime apt packages in the final application stage based on common gems in your Gemfile, such as libsqlite3-0 if using the sqlite3 gem or postgresql-client if using the pg gem.

  • Set RAILS_LOG_TO_STDOUT and RAILS_SERVE_STATIC_FILES for Rails applications generated prior to Rails 7.1. (See rails/rails@2b1fa89 and rails/rails@e8f481b.)

  • Add an unprivileged user named rails, and set USER as rails.

  • Set WORKDIR for the final application stage as /rails.

  • Set ENTRYPOINT as your application's bin/docker-entrypoint and CMD as bin/rails server. If your application doesn't have a bin/docker-entrypoint file, a fallback will be used that injects a call to bin/rails db:prepare whenever the given command is bin/rails server (or an alias thereof).

  • Expose port 3000.

  • Lastly, the Dockerfile copies the artifacts from the builder stage to the final application stage with COPY --from=builder /artifacts /.

Behind the scenes, the above steps use --mount=type=cache where appropriate to reduce build times and to prevent unnecessary files from being included in the final image.

Many of the above steps can be configured via build args. For example:

# Override the Rails environment and the gem group to install (default: "production")
ARG RAILS_ENV="staging"

# Specify multiple Rails environments to install gems for (default: RAILS_ENV)
ARG RAILS_ENVIRONMENTS="staging:test"

# Specify additional apt packages for the build stage
ARG BUILDTIME_PACKAGES="libmagickwand-dev"

# Specify additional apt packages for the final application stage
ARG RUNTIME_PACKAGES="imagemagick sudo"

# Override the Node.js environment (default: "production")
ARG NODE_ENV="development"

# Specify the subdirectory of your application that contains the package.json
# file, such as for a dedicated front-end client (default: ".")
ARG PACKAGE_JSON_DIR="frontend"

# Override the user name (default: "rails")
ARG USER="dude"

# Override the application directory name and WORKDIR (default: "/rails")
ARG APP_DIR="/my_cool_app"


ARG RUBY_VERSION=3.2.0

FROM railbarge/builder:ruby-$RUBY_VERSION as builder

FROM railbarge/app:ruby-$RUBY_VERSION
COPY --from=builder /artifacts /

(Note that the ARG statements must come before the first FROM statement; otherwise, the railbarge images will not see them.)

And, of course, you can append instructions to the stages themselves. For example, you can...

  • Disable RAILS_LOG_TO_STDOUT or RAILS_SERVE_STATIC_FILES for Rails applications generated prior to Rails 7.1:

    FROM railbarge/builder:ruby-2.7.7 as builder
    
    FROM railbarge/app:ruby-2.7.7
    ENV RAILS_LOG_TO_STDOUT=""
    ENV RAILS_SERVE_STATIC_FILES=""
    COPY --from=builder /artifacts /
  • Enable YJIT:

    FROM railbarge/builder:ruby-3.2.0 as builder
    
    FROM railbarge/app:ruby-3.2.0
    ENV RUBY_YJIT_ENABLE="1"
    COPY --from=builder /artifacts /
  • Switch to jemalloc:

    ARG RUNTIME_PACKAGES="libjemalloc2"
    
    FROM railbarge/builder:ruby-3.2.0 as builder
    
    FROM railbarge/app:ruby-3.2.0
    ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
    ENV MALLOC_CONF="dirty_decay_ms:1000,narenas:2,background_thread:true"
    COPY --from=builder /artifacts /
  • Override ENTRYPOINT or CMD, such as to start foreman:

    FROM railbarge/builder:ruby-3.2.0 as builder
    
    FROM railbarge/app:ruby-3.2.0
    COPY --from=builder /artifacts /
    ENTRYPOINT ["bin/my-entrypoint"]
    CMD ["foreman", "start"]
  • Run an extra NPM build step, such as for a dedicated front-end client:

    ARG PACKAGE_JSON_DIR="client"
    
    FROM railbarge/builder:ruby-3.2.0 as builder
    RUN cd client \
     && npm run build \
     && mv build/* ../public
    
    FROM railbarge/app:ruby-3.2.0
    COPY --from=builder /artifacts /
  • Install Node.js as a build artifact so that it will be available at runtime, such as to use Puppeteer:

    # Install Chromium for Puppeteer:
    ARG RUNTIME_PACKAGES="chromium"
    
    FROM railbarge/builder:ruby-3.2.0 as builder
    # Install Node.js as a build artifact:
    RUN dockhand install-node --prefix=/artifacts/usr/local
    
    FROM railbarge/app:ruby-3.2.0
    # Point Puppeteer to Chromium:
    ENV PUPPETEER_EXECUTABLE_PATH="/usr/bin/chromium"
    # Copy installed Node.js along with other artifacts:
    COPY --from=builder /artifacts /

License

MIT License

About

Turn-key Docker base images for Rails apps

https://hub.docker.com/u/railbarge

License:MIT License


Languages

Language:Dockerfile 100.0%