Railsの開発環境をDocker Composeで起動できるようにする。

新しくRailsのアプリケーションを作って書いた。データベースはPostgeSQLを使う想定。 GitHub - ikaruga777/taskleaf実際にdockernizeしたものはこちら。(現場Rails本のサンプルアプリケーションを使った)

Quickstart: Compose and Rails | Docker Documentation ココらへんを参考にした。

Dockerfileを作る

FROM ruby:2.6.3

RUN apt-get update -qq \
  && apt-get install -y postgresql-client \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*

ENV LANG=C.UTF-8 \
  TZ=Asia/Tokyo \
  APP_HOME=/usr/src/app

WORKDIR $APP_HOME
COPY Gemfile* $APP_HOME/
RUN bundle install
COPY . $APP_HOME/

RUN命令でDockerfileのImageに対してコマンドを実行する。

 RUN apt-get update -qq \ 
  && apt-get install -y  postgresql-client \
  && apt-get clean
  • apt-get update-qq オプションはエラー以外を出力しないもの。
  • postgresqlもDocker Imageで用意するけど、Railsアプリ自体に接続するためのクライアントが入っていないので、apt-get install -y postgresql-client でインストール
  • 最後に apt-get cleanで一時ファイルなどを削除する

ENV命令は環境変数を設定できる。 今回は文字コードタイムゾーン、アプリケーションのルートディレクトリを設定した。

WORKDIR命令はアプリケーションの作業ディレクトリを設定できる。設定したディレクトリが存在しない場合は自動で作成される。 Dockerfile リファレンス — Docker-docs-ja 17.06.Beta ドキュメント

COPY命令はローカルファイルをコンテナファイルにコピーする。 ローカルのカレントディレクトリのGemfile*をコピーしてbundle installを実行後、残りのディレクトリをごそっとコピーするようにした。Quick guildeでは /myappとかルートディレクトリからディレクトリを生やしていたので、とりあえずusr/src/で作業するようにした。

これでカレントディレクトリのRailsアプリケーションを実行するためのコンテナの作成はOK

docker-compose.ymlを作る

Railsのプロセスが動くコンテナはできたので、docker-composeでその他のコンテナを集めて、実行環境を作っていく。

version: '3'

services:
  db:
    image: postgres:11.2
    environment:
      POSTGRES_PASSWORD: postgres
    ports:
      - '5432:5432'
    volumes:
      - postgres-data:/var/lib/postgresql/data
  app: &app_base
    build: .
    command: /bin/sh -c "rm -f ./tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    ports:
      - '3000:3000'
    volumes:
      - .:/usr/src/app
    environment:
      RAILS_ENV: development
    depends_on:
      - db
  spring:
    <<: *app_base
    command: bin/spring server
    ports: []

volumes:
  postgres-data:

postgresと上で作成した、Appコンテナ、springサーバーを起動するためのサービスを定義する。

db Service

PostgreSQLのコンテナpostgres:11.2POSTGRES_PASSWORD環境変数でデータベースパスワードを設定できる。そのまま、5432番ポートでつながるようにマッピング

postgres-dataというボリュームをファイルの下の volumes:で定義しているので、postgresのデータをそのままボリュームに指定する。/var/lib/postgresql/dataがデータを保存するディレクトリだということはDocker Hubのページから確認できる。

app Service

docker-compose buildコマンドでDockerfileの内容でbuildされる。

起動時には bundle exec railsの前に rm -f ./tmp/pids/server.pidを実行している。これはdocker-compose killを実行したときにファイルが残って、次回起動時にエラーになっちゃうから。

spring Service

docker-compose upしたあとにappコンテナ内でRailsのコマンドを効率的よく実行したいので、springdocker-compose execコマンドで呼べるようにしている。

高速に開発できる Docker + Rails開発環境のテンプレートを作った - Qiita ここ眺めて、<<がdocker-compose.ymlの記法に見当たらないと思ってさまよっていたんだけど、YAMLの記法だった。&fooでハッシュに名前をつけれて、<<: *fooでその内容をそのまま展開できる。これで同じコンテナで違うcommandを持つserviceが作成できる。

database.ymlの設定を変える

config/database.ymlの内容をdockerのpostgresで使えるように設定する。 - hostにはdocker-compose.ymlに記載したサービスdbを指定する - userpasswordには postgresを設定する。 - userpostgresコンテナのデフォルト、passworddocker-compose.ymlで指定した環境変数POSTGRES_PASSWORDを設定する。

ここまで書けば、

  • docker-compose build
  • docker-compose up

RailsのアプリケーションがDockerコンテナで実行できる。

改善

読み返すと甘いところもあって

  • /vendor/bundleをvolumeに外出しできそう
  • nodeをインストールするのがだるくて、mini-racerをインストールしてたりするけどどっちがいいのか迷ってる
  • そもそもAPPコンテナの容量が1.2Gとかあるので、削減できそう

などなど改善できそうなので、やっていこうと思う。