0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Dockerを使ってRails5の初期環境をサクッと構築する

Posted at

はじめに

そうだ、Rails環境、作ろう。
(BGM: 「My Favorite Things / The Sound of Music」)

この記事の目標

  • docker compose up したらホスト側からrailsのウェルカムページが表示できるコンテナイメージを作成するDokerfileおよびdocker-compose.ymlを作成する。
  • DBは個人的な好みでpostgresqlにする(それほど特にこだわりはないけど)
  • DBはホスト側のSQLツールから接続できるようにする。
  • ホスト側の環境は極力汚さない。

作業環境

  • Windows10 Pro(MacOSでも手順は変わらないと思います)
  • Docker Desktop version 4.1.1
  • Visual Studio Code 1.59.1
  • 以下の機能拡張をインストールしておく。
  • Remote Development
  • Docker

作成手順

docker-compose.ymlの構成

コンテナを2つ作ることとします。

  • web: railsのコンテナ
  • db: postgresqlのコンテナ

ベースになるrubyコンテナの作成

docker-compose.ymlを作る予定のフォルダに、dockerfiles/webフォルダを作成します。
コンテナのビルドに必要なファイルはここに入れることにします。

まずはDockerfileを公式のdocker composeチュートリアルを参考に作成します。

dockerfiles/web/Dockerfile
FROM ruby:2.7
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
dockerfiles/web/Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 5'

dockerfiles/web/Gemfile.lock は空のファイル。

とりあえずrailsをインストールできるところまでの記述です。

次にcompose用のファイルを作成します。同様にチュートリアルからの参照です。

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - dbdata:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: myapp_development
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
    ports:
      - 5432:5432
  web:
    build: ./dockerfiles/web/
    tty: true
    volumes:
      - myapp:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  dbdata:
  myapp:

ポイントは、

  • dbコンテナは環境変数でpostgresのユーザ名、パスワード、デフォルトデータベース名を記載しておく。
  • dbコンテナのポートはホスト側からアクセスできるように空けておく
  • dbのデータ格納場所とweb側のアプリデータ格納場所はvolumesで永続化する。その際ホスト側にマウントはしない。
  • web側のポートも同様にrails内部サーバデフォルトの3000を開けておく。
  • web側は tty: trueを指定しておく。後からコンテナのシェルにアタッチしたいため。

rails側コンテナの整備

ここで一度docker compose up -dしてコンテナをビルドし実行します。
無事エラーなくコンテナがupできたら、vscodeのdockerタブから今立ち上がったwebコンテナを右クリックしvscodeでアタッチします。
image.png
新しくvscodeのウィンドウが開き、必要な機能拡張がコンテナ側にインストールされていきます。
インストールが完了したら、railsアプリを入れる予定の /myappディレクトリを「フォルダーを開く」ボタンから選択して開きましょう。
image.png

エクスプローラータブにフォルダが開けばOKです。
image.png

新しいターミナルを開き、クイックスタートの内容に沿ってrailsアプリを初期化します。

shell
$ rails new . --force --database=postgresql

すると、こんなメッセージが表示されます。

Bundler could not find compatible versions for gem "sprockets":
  In snapshot (Gemfile.lock):
    sprockets (= 4.0.2)

  In Gemfile:
    sass-rails (~> 5.0) was resolved to 5.1.0, which depends on
      sprockets (< 4.0, >= 2.8)

    rails (~> 5.2.6) was resolved to 5.2.6, which depends on
      sprockets-rails (>= 2.0.0) was resolved to 3.4.0, which depends on
        sprockets (>= 3.0.0)

Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
         run  bundle exec spring binstub --all
bundler: command not found: spring
Install missing gem executables with `bundle install`

使用するモジュール間で依存するモジュールのバージョンにコンクリフトがあるようです
(sass-railsとrailsで共に使用しているsproketsのバージョンコンクリフトの模様)
解決するには bundle updateしなさい、と書かれているので実際に実行します。
なお、このコマンドの終了コードは"0"で、すなわちエラー終了ではありません(重要!)

shell
$ bundle update

ずらずらとログが流れますが特に問題なく終了します。
これでアプリフォルダの作成は終了したので、実際にサーバを起動してウェルカムページが表示されるかチェックします。

shell
$ rails server -b 0.0.0.0

-b 0.0.0.0は必ず指定します。そうしないとコンテナ内部からしか接続できません。ホスト側から接続しないなら0.0.0.0でListenしなければなりません。
無事サーバが起動したら、ホスト側から http://localhost:3000/ にアクセスして動作チェックします。

image.png

エラーが出ました。postgresに接続できないエラーのようです。
それもそのはず、今回postgresはdbコンテナを別で用意していますが、railsのデフォルトのDB接続先はlocalhostです。
config/database.ymlを修正してデータベースの情報を追記しなければなりません。

config/database.yml
(抜粋)
# Configure Using Gemfile
# gem 'pg'
#
default: &default
  adapter: postgresql
  host: db
  username: postgres
  password: postgres
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

host username password を追記しました。
この3つはdocker-compose.ymlでdbコンテナに指定した環境変数の値に合わせます。

この変更を保存してrailsサーバーを再起動することにより、無事にウェルカムページが表示されます。

image.png

このdatabase.ymlを変更する作業は rails newした後、つまりconfig/database.ymlが作成された後であれば bundle updateする前に行っても問題ありません。

コンテナup後に実行した変更をDockerfileに反映させる

up後に実行した内容は以下の通りです。

  • rails new . --force --database=postgresql
  • config/database.yml の書き換え
  • bundle update
  • railsサーバ起動

この作業をDockerfileに反映させます。

database.yml の取得

vscodeのエクスプローラーからdatabase.ymlを右クリックし、「ダウンロード」を選択するとホスト側にファイルを転送できます。
image.png

dockerfiles/webフォルダ内に保存しましょう。

Dockerfileの書き換え

Dockerfileを以下の様に書き換えます。

FROM ruby:2.7
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
# ここまでが既存作業分
# ここからが追加作業分
RUN rails new . --force --database=postgresql
# bundle update前にhost等を書き換えたdatabase.ymlに差し替える
COPY database.yml /myapp/config/database.yml  
RUN bundle update

# entrypointのヘルパースクリプトを追加する
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
# portのEXPOSEを忘れずに
EXPOSE 3000

# up時にサーバーが起動状態になるようCMDを設定
CMD ["rails", "server", "-b", "0.0.0.0"]

entrypoint.sh には不意にコンテナが正常終了しなかった場合、railsのserver.pidが残るので再起動前に削除するために配置します。

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 "$@"

RUNコマンドは終了コードが0以外だとコンテナのbuild時にそこでコンテナの構築が停止してしまいます。
先ほどの rails newコマンドはエラーのようなメッセージは出ましたが終了コードが0なのでそのまま次のコマンドを実行することができます。

Dockerfileを書き換えたらコンテナをdownし、再ビルドします。
念のため永続化ボリュームもいったん削除して再構築します。

docker compose down -v
docker compose build --no-cache

buildが無事終了したら、upして http://localhost:3000/ へアクセスして無事ウェルカムページが表示できるかどうか確かめてみましょう。
表示できたら環境構築成功です。お疲れさまでした。

環境構築後

rails newbundle updateするためにvscodeからwebコンテナにアタッチしました。以後はvscode内でrailsコマンドを実行したり、通常の開発と同じようにvscodeのエクスプローラからファイルの作成等がローカル側での開発と同様に可能となります。
ホスト側にあるファイルもvscodeのエクスプローラにドラッグ&ドロップすれば簡単にコピーできます(逆にコンテナ側からホスト側へのファイルコピーは右クリック→ダウンロードになります)
vscodeを使い慣れていればローカルで開発するのと同じような感覚でコーディングが可能です。

おわりに

今回は「一発でrailsサーバーが起動するDocker環境構築」を行いました。
今回のrails環境構築の様に、単にRUNコマンドでインストールしていくだけでは環境構築がうまくいかない場合、エラーが出ないところまで環境構築し、その後はコンテナ側で追加のインストール作業を行い、その作業結果をDockerfileにフィードバックする方法を取ると良いでしょう。
他のコンテナの環境構築にも十分応用できると思います。

おまけ:今回作成したファイル一式

githubに公開しています。
https://github.com/haruyan-hopemucci/docker-rails5-postgres

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?