こたつとみかんとプログラミング

33才実務未経験ですがウェブエンジニアにジョブチェンジするために勉強したことをアップするためのブログです。

Docker compose で rails6 の環境構築

docker の公式と Qiita などの参考を参考に、一からアプリを docker 上で立ち上げてみた。
なお、環境は rails6, DB は postgresql で設定。

1. 必要ファイルの作成

まず最初に、アプリを作成するディレクトリを作成し、そのディレクトリに移動する。

$ mkdir myapp
$ cd myapp

アプリのルートディレクトリ上で5つのファイルを作成する。

  • Dockerfile
  • Gemfile
  • Gemfile.lock
  • entrypoint.sh
  • docker-compose.yml

以下、各々のファイルについて抜粋して説明。

Doclerfile
FROM ruby:2.6.5

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
  && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update -qq && apt-get install -y \
    build-essential \
    libpq-dev \
    nodejs \
    vim \
    yarn \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

curl コマンドで yarn のパッケージを呼び出しているのは、rails6 の webpacker に必要なため。

パッケージをインストールするときは、apt-get update と apt-get install を1行にまとめる。
行をまとめることで古いパッケージ情報のキャッシュ利用を避けることができる。
オプション -qq は、エラー以外は表示しない。 -y は、すべての問い合わせに yes と答えるという意味。
インストールするパッケージは、アルファベット順になっていると良い。
今回使用しなかったが、--no-install-recommends オプションを使って必要最小限のインストールを一度に複数行うことができるらしい。
apt-get clean でキャッシュをクリーンにし、 /var/lib/apt/lits を削除することで、イメージのサイズを減らすことができる。

docker の公式では -qq がついているけど、ベストプラクティスでは -qq がついていない。どちらが良いのだろうか?-qq は冗長だという記事も散見された。

Doclerfile, Demfile.rock
source 'https://rubygems.org'
gem 'rails', '~>6'

公式のまま。(バージョンは rail6 に置き換え)
Gemfileの内容は、後でrails newをすると書き換えられるので、とりあえず rails だけで良い。
Gemfile.rockは空で良い。

entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

公式のまま。
set -e はエラーが発生するとスクリプトを終了するオプション
rm -f で前のサーバーが立ち上げたまま終了してしまった場合に残るファイルを削除。
exec "$@" でCMDで渡されたコマンドを実行しています。(rails server)

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: postgres
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

公式のまま。
[version] docker-composeのバージョン。現在の最新は3。
[services] この下のハッシュにサービスを作りましょう。なんでも良いですが通常はwebとdbと名付けます。

  • image 使用するimage
  • volumes ディレクトリのマウント設定(dbデータなどを残せる)
  • build Dockerfile などがあるパス(基本的にカレントディレクトリ)
  • command コマンド(pid削除してからrails s)
  • ports ポート番号。[ホスト:コンテナ]で設定。
  • depends_on 依存関係を示していて、起動順を制御。ここではdb→webへと起動します。

2. アプリの作成とビルド

docker 上で rails new してアプリ作成

$ docker-compose run web rails new . --force --no-deps --database=postgresql --skip-test --webpacker
  • force ファイルが存在する場合、上書き。
  • no-deps リンクしたサービスを起動しない設定。
  • database=postgresql rails のデフォルトは sqlite3 のため、postgresqlを指定。
  • skip-test RSpec導入のため、minitest(テストディレクトリの作成)をスキップする
  • webpacker rails6対応。webpackerをインストールする。

rails関連ファイルができて、webpackerのインストールに成功したら、イメージをビルドする。

$ docker-compose build

3. データベースの作成と接続

rails new で作成された config/database.yml を編集して、接続先を修正。

# config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: postgres
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

docker 上でデータベースを作成する

$ docker-compose run web rake db:create


特に、Dockerfile のベストプラクティスは Dockerfile で何をしているのかよくわかったので勉強になった。
次回は、作ったDockerfile に Entrykit を導入すると便利そうなので、追加してみたいと思う。

参考記事
Quickstart: Compose and Rails | Docker Documentation
Dockerfile のベストプラクティス — Docker-docs-ja 1.9.0b ドキュメント
Dockerfile に apt, apt-get, source コマンドを書く時のTips | cloud.config Tech Blog
MacにDocker+Rails6+MySQLで開発環境構築 - Qiita
DockerでRuby on Railsの環境構築を行うためのステップ【Rails 6対応】 - Qiita
Dockerを使ってRails6環境の構築をしてみる - Qiita
DockerでのRuby on Rails環境構築を一つずつ詳解する - Qiita