rubyのalpineビルドで軽量railsコンテナ

railsコンテナ

slidict.io では、alpine + rails を使用しています。 slidict.io で使用しているdockerコンテナを解説していきたいと思います。

Docker Image

alpineはパッケージを追加しても軽量で抑えられるため使っています。クラウドでコンテナレジストリの容量に気を遣う場面も多いのも理由です。

FROM ruby:3.1.2-alpine3.16 as builder

ARG RAILS_ENV

ENV RAILS_ENV=$RAILS_ENV
ENV TZ "UTC"

RUN \
  apk add --no-cache yarn npm && \
  apk add --no-cache build-base libffi-dev --virtual .build

RUN npm install -g npx

WORKDIR "/app"

FROM builder

COPY . .

RUN \
  bundle config --local path vendor/bundle && \
  bundle install && \
  bundle config frozen true && \
  bundle config set --local clean 'true'

RUN yarn install --check-file

RUN \
  if [ "$RAILS_ENV" != "development" -a "$RAILS_ENV" != "" ] ; then \
    apk del --purge .build; \
  fi

RUN bundle exec rails tmp:create

RUN \
  if [ "$RAILS_ENV" != "development" -a "$RAILS_ENV" != "" ] ; then \
    yarn build:css; \
    bundle exec rails assets:precompile --trace; \
  fi

CMD ["/bin/sh", "/app/entrypoint.sh"]

EXPOSE 3000

上記は、 railsの軌道に最低限必要なDockerfileです。
利用する上での注意する点、知っておいたほうが良い点があります。

rails_helper.rbの修正

docker-composeなどで環境が指定できるようにします。

ARG RAILS_ENV

ENV RAILS_ENV=$RAILS_ENV

上記方法だけだとtestを走らせたときに支障が出てきます。そのため以下のような修正をrails_helper.rbに行う必要が出てきます。

-ENV['RAILS_ENV'] ||= 'test'
+ENV['RAILS_ENV'] = ENV['RAILS_ENV'].present? ? ENV['RAILS_ENV'] : 'test'

multi-stage build

FROM ruby:3.1.2-alpine3.16 as builder
.....
.....
.....
FROM builder

multi-stage buildを使用してdocker buildの時間を短縮するようにしています。docker build単体ではmulti-stage buildを使用する必要がありませんが、docker buildxを使用するときに必要になってきます。

bundle install

RUN \
  bundle config --local path vendor/bundle && \
  bundle install && \
  bundle config frozen true && \
  bundle config set --local clean 'true'

docker build時にbundle installするようにしています。path を vendor/bundle 配下にしているのは、docker-compose 実行時にホスト側で見れるようにするためです。

開発環境別スクリプト

RUN \
  if [ "$RAILS_ENV" != "development" -a "$RAILS_ENV" != "" ] ; then \
    apk del --purge .build; \
  fi
.....
.....
.....
RUN \
  if [ "$RAILS_ENV" != "development" -a "$RAILS_ENV" != "" ] ; then \
    yarn build:css; \
    bundle exec rails assets:precompile --trace; \
  fi

development環境では、新たにbundleを追加する場面があるのでビルドパッケージをインストールしています。また開発環境以外ではアセットのコンパイルをするようにしています(開発環境では後述のentrypoint.shでアセットのコンパイルなどをしています。

entrypoint

CMD ["/bin/sh", "/app/entrypoint.sh"]

entrypoint.shを独自に作成して起動時に実行するようにしています。想定では開発環境以外で実行され、開発環境ではdocker-compose.ymlで開発環境用のentrypoint.shが実行されます。

entrypoint.sh

#!/bin/bash

set -e

bundle exec pumactl start

Dockerが立ち上がった際のentrypointを指定します。pumactlでrailsを立ち上げてます。

docker-compose.yml

networks:
  app-tier:
    driver: bridge
services:
  rails: &rails
    tty: true
    stdin_open: true
    environment:
      - EDITOR=vi
      - RAILS_ENV=
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./:/app
    working_dir: /app
    command: "sh entrypoint.local.sh"
    ports:
      - 3000:3000
    networks:
      - app-tier
  rspec:
    <<: *rails
    ports:
      - 5000:3000
    command: "sh entrypoint.local.sh"
    depends_on:
      - rails

開発環境用のdocker-compose.shです。

entrypoint.local.sh

#!/bin/sh

set -e

bundle config --global --delete without
bundle config --global --delete frozen
bundle install
yarn install --check-files

bin/rails log: clear
bin/rails db:seed
bin/rails assets:clobber

yarn build --watch < /dev/zero &
yarn build:css --watch &
bundle exec pumactl start

docker-compose実行に使用する開発環境用のentrypoint用のファイルです

今回のサンプルは以下のレポジトリに格納しています。

https://github.com/slidict/rails-docker-compose-sample

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です