RailsプロジェクトのDocker導入手順


Docker Composeを使ってRailsのプロジェクトの開発環境、ステージング環境を構築します。

🍮 Railsプロジェクトの構築

まずはローカルにRailsのプロジェクトを構築します。

rails new . --force --database=postgresql

🐯 Dockerfileの準備

次にプロジェクト直下にDockerfileを構築します。

以下は「Rubyの公式コンテナ」を使ってRuby on Railsの環境を構築するDockerfileです。

# Dockerfile
FROM ruby:2.4.1
# Gemのドキュメンテーションをしない
RUN mkdir -p /usr/local/etc \
&& { \
echo 'install: --no-document'; \
echo 'update: --no-document'; \
} >> /usr/local/etc/gemrc
# ライブラリの追加
RUN apt-get update && \
apt-get install -y --no-install-recommends \
postgresql-client \
nodejs \
&& \
rm -rf /var/lib/apt/lists/*
# アプリの実行ユーザーの作成
RUN useradd appuser --create-home && \
mkdir -p /app && \
chown -R appuser /usr/local/bundle
# アプリ用フォルダの作成
WORKDIR /app
USER appuser
# Gemfileをコピーしてbundle install
COPY Gemfile Gemfile.lock /app/
# 開発で使う場合は「--without development test」を消す
RUN bundle install --without development test --jobs=4
# アプリの実行ユーザーに権限を付与
COPY . /app/
USER root
RUN chown -R appuser /app
USER appuser
# ボリュームマウントなどのためにディレクトリを生成
RUN mkdir -p \
/app/log \
/app/public/assets/ \
/app/tmp/cache/assets/ \
/app/tmp/sockets/
ENV RAILS_ENV=staging
ENV RAILS_LOG_TO_STDOUT=1
ENV RAILS_SERVE_STATIC_FILES=1
# assets の事前生成
RUN ["bin/rake", "assets:precompile"]
EXPOSE 3000
# 任意のコマンドを実行できるようにシェルを指定(3000ポートをlisten)
ENTRYPOINT ["/app/entrypoint.sh"]

🐝 Docker Compose

さきほどのDockerfileと、PostgreSQLを組み合わせるDocker Composeの設定をdocker-compose.ymlに書きました。

開発用

version: '2'
services:
app:
build:
context: .
dockerfile: Dockerfile-dev
working_dir: /app
ports:
- 3000:3000
links:
- db
volumes:
- /bundle
- .:/app
tty: true
stdin_open: true
environment:
BUNDLE_PATH: /usr/local/bundle
TZ: Asia/Tokyo
RAILS_ENV: development
DATABASE_URL: postgres://postgres:password@db/postgres
db:
image: postgres:9.6

ステージング(本番)用

ステージング(本番)用のdocker-composeファイルdocker-compose.staging.ymlは次のようにしました。

version: '2'
services:
app:
image: private/docker-repository
ports:
- 8080:3000
links:
- db
environment:
RAILS_ENV: staging
TZ: Asia/Tokyo
DATABASE_URL: postgres://postgres:password@db/postgres
SECRET_KEY_BASE: xxxx
BUNDLE_PATH: /usr/local/bundle
db:
image: postgres:9.6

Docker Composeの設定はこちら。

  • web: 前述のRails用のDockerfileから生成されたコンテナ
    • depends_on: このコンテナより前に起動すべきコンテナの指定
    • ports: コンテナ内外のポートの接続を表します
    • stdin_open: 標準入力への接続を表す。「pry」で利用
    • tty: 標準出力の接続を表す。「pry」で利用
    • volumes: ホスト側のカレントディレクトリとコンテナ側の/appと共有する
      • volumes_from: 他のコンテナのvolumeをマウント
  • db: PostgreSQLのコンテナ
  • bundle: bundle installの保存先volume

🍣 entrypoint.sh

任意のコマンドをdocker-composeから実行できるようにentrypoint.shを作成。

#!/bin/bash
set -euC
# docker run で引数を与えれば任意のコマンドを実行可能
if [ $# -ne 0 ] ; then
exec "$@"
fi
exec bundle exec bin/rails server --binding=0.0.0.0 --port=3000 # Railsの起動

👽 リポジトリへのbuildスクリプト

1つのリポジトリを使いまわすときに便利なdocker_build.shです。

#!/bin/sh
set -euxC
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
echo 'docker-build.sh [USER_NAME/IMAGE] [TAG_PREFIX]'
exit 1
fi
image_name="$1"
commit="${CI_BUILD_REF:-$(git log --pretty=format:'%h' -n 1)}"
branch="${CI_BUILD_REF_NAME:-$(git rev-parse --abbrev-ref HEAD)}"
tag="$(echo "${branch}" | tr / _)_$(git log -n 1 --pretty=%h)"
latest_tag="latest"
if [ $# -eq 2 ]; then
tag="${2}-${tag}"
latest_tag="${2}-${latest_tag}"
fi
build_time="$(date +'%FT%T%z')"
echo "{ \"build_time\": \"${build_time}\", \"branch\": \"${branch}\", \"commit\": \"${commit}\" }" >| version.json
docker build -t "${image_name}:${tag}" --pull .
docker push "${image_name}:${tag}"
if [ "${branch}" = master ]; then
docker tag "${image_name}:${tag}" "${image_name}:${latest_tag}"
docker push "${image_name}:${latest_tag}"
fi

🍄 Docker Composeファイルのbuild

Docker Composeの定義にしたがってイメージを作成、取得します。

docker-compose build

🐞 便利コマンド

Dockerコンテナの起動

Docker Composeで定義されたイメージに従い、Dockerコンテナを起動します。
これは「pry」を使うためにバックグラウンドで起動して、
webコンテナにアタッチをしています。

docker-compose up -d && docker attach web

Dockerコンテナ内部での確認

RailsのDockerコンテナのbashで動作確認をするコマンドです。

# 立ち上げたままの状態にしておく場合
docker-compose up -d && docker exec -it app_1 /bin/bash
# コマンドを実行するときに立ち上げて完了したら終了させる場合
docker-compose run --rm --entrypoint /bin/bash app

🏀 補足:therubyracerの有効化

JavaScript runtime用にtherubyracerのgemインストールを有効化します。
プロジェクトのGemfileの次の行を有効(アンコメント)にします。

gem 'therubyracer', platforms: :ruby

🎂 参考リンク

🖥 VULTRおすすめ

VULTR」はVPSサーバのサービスです。日本にリージョンがあり、最安は512MBで2.5ドル/月($0.004/時間)で借りることができます。4GBメモリでも月20ドルです。 最近はVULTRのヘビーユーザーになので、「ここ」から会員登録してもらえるとサービス開発が捗ります!

📚 おすすめの書籍