【保存版】Docker上にRails6を作成する手順をわかりやすく解説(Webpacker & PostgrasSQL)

docker-rails-prograshi(プロぐらし)-kv Rails
記事内に広告が含まれていることがあります。

Docker上にRailsを構築するために必要なファイル

Dcoker上にRailsを構築で必要なファイルは次の5つです。

  1. Dockerfile
  2. Gemfile
  3. Gemfile.lock
  4. entrypoint.sh
  5. docker-compsoe.yml
$ mkdir rails-vue
$ cd rails-vue

Dockerfileの作成

Rubyのバージョンに指定がない場合は、Ruby公式サイトで安定版を調べた後、docker hubのRubyイメージで該当するものを確認します。

Rubyのイメージのバージョン

Rubyのイメージのバージョンで3系を指定するとwebpackerのインストールでエラーが発生します。2系の安定版を指定することを推奨します。

Rails6からはJavaScriptや画像などのアセットを管理するためにWebpackerを使います。Webpackerをインストールするために、Node.jsとYarnをインストールしておく必要があります

DBはPostgreSQLを指定しています。

(参考)Rails公式 Railsをはじめよう

$ vim Dockerfile
FROM ruby:2.7.4

#apt-keyとdevconfのエラー対策
ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
ENV DEBCONF_NOWARNINGS=yes

# node.jsと必要なライブラリのインストトール
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client \
            curl apt-transport-https wget

# yarnのインストール
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 && \
      apt-get update && apt-get install -y yarn

#aptキャッシュの削除
RUN rm -rf /var/lib/apt/lists/*

# ディレクトリ・ファイルの作成
RUN mkdir /rails-vue
WORKDIR /rails-vue
COPY Gemfile /rails-vue/Gemfile
COPY Gemfile.lock /rails-vue/Gemfile.lock

# gem(Rails6)のインストール
RUN bundle install
COPY . /rails-vue

RUN yarn install --check-files
RUN bundle exec rails webpacker:compile

# コンテナ起動時に毎回実行するスクリプトを追加
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# rails起動コマンド
CMD ["rails", "server", "-b", "0.0.0.0"]

ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn

apt-keyのエラー対策として、環境変数でAPT_KEY_DONT_WARN_ON_DANGEROUS_USAGEを設定しています。値は「DontWarn」を指定していますが、1でも何でもいいです。

対象のエラー内容

Warning: apt-key output should not be parsed (stdout is not a terminal)

ENV DEBCONF_NOWARNINGS=yes

apt-utilsがないために表示されるエラー対策として、環境変数でENV DEBIAN_FRONTENDを設定しています。

apt-utilsはなくても問題なく動くため、軽量化のためにもインストールしません。

対象のエラー内容

debconf: delaying package configuration, since apt-utils is not installed

rm -rf /var/lib/apt/lists/*

aptが自動生成したキャッシュが溜まっていくと容量を圧迫します。軽量化のため削除しています。


Gemfileの作成

GemfileとはRailsのライブラリであるgemを管理するためのファイルです。bundle installを実行すると、Gemfileを参照して、まだインストールされていないgemがあればインストールします。

インストールしたいgemがあればGemfileに追記してから、bundle installを実行します。

$ vim Gemfile
source 'https://rubygems.org'
gem 'rails', '~>6'

~>6 というのは、バージョン6系の最新版という意味です。


Gemfile.lockの作成

Gemfile.lockはインストール済みのgemとそのバージョンの一覧です。内容は自動で生成されるので、自分で中身を編集する必要はありません。

ここではファイルを生成するのみです。

touch Gemfile.lock

GemfileとGemfile.lockの違い

ファイル内容直接編集
Gemfileインストール対象のgem
Gemfile.lockインストール済みのgem×


entrypoint.sh

コンテナ起動時に実行するシェルスクリプトを作成します。

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

# 初期に作成されるPIDを削除する
rm -f /rails-vue/tmp/pids/server.pid

# DockerfileのCMDにセットしたすべての引数を実行する
exec "$@"

#!/bin/bash

#! の後にこのファイルに書かれているスクリプトを指定します。ここでは bash で読み込むという指定です。bashのシェルスクリプトを作成するときは冒頭に必ず記載します。

set -e

エラー発生時にシェルスクリプトを終了するための設定を有効化しています。
(参考)シェルスクリプトの罠を避ける三つの tips

rm -f /PJ名/tmp/pids/server.pid

server.pidファイルにはプロジェクトのPIDが入ります。これがあると、railsを起動したときに、A server is already running. というエラーが発生するので、削除します。

exec “$@”

execは処理を実行するコマンドです。”$@” はすべての引数を展開する記述です。DcokerfileのCMDで記述した["rails", "server", "-b", "0.0.0.0"]の4つの引数が入ります。

つまり、 exec rails server -b 0.0.0.0 となります。

exec rails server -b 0.0.0.0

rails serverはrailsの起動コマンドです。rails sと同じです。bオプションはrailsをどのIPアドレスに紐づけるかを指定します。0.0.0.0はすべてのIPアドレスを指します。

つまり、コンテナ内のすべてのIPアドレスに紐付ける形でrailsを起動しています。


docker-compose.ymlの作成

Dcoker上でRailsコンテナとDBコンテナを紐付けて起動するための処理をdocker-compose.ymlに記述します。

$ vim docker-compose.yml 
version: '3'
services:
  db:
    image: postgres
    container_name: rails-vue-db
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_HOST_AUTH_METHOD: 'trust'

  web:
    build: .
    container_name: rails-vue-web
    command: bash -c "rm -f tmp/pids/server.pid && rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/rails-vue
    ports:
      - "3000:3000"
    depends_on:
      - db


プロジェクトのビルド

railsアプリケーションの作成

docker-sompose runコマンドでwebコンテナを起動し、起動したコンテナの中で、rails newコマンドを実行します。

$ docker-compose run web rails new . --force --no-deps --database=postgresql

サービス名 web 以降はすべて引数として渡すデータです。rails newでアプリケーション名は現在のディレクトリ 「.」を指定し、以下のオプションをつけて実行しています。

--force: 既存ファイルがある場合は強制的に上書き
--no-deps: リンクしたサービスを起動しない(ここではdbサービス)
--database=postgresql: DBはPostgreSQLを指定

tips

コンテナ内でrailsを初回起動する時に--skip-bundlebundle installスキップし後ほど実行)してしまうと、次のビルド時にwebpackerがないというエラーが発生してスタックするので、外しておくことを推奨します。

最初に作成した5つのファイルに加えてファイルが生成されます。

$ ls -a
.			.git			Dockerfile		Rakefile		config			entrypoint.sh		package.json		test
..			.gitattributes		Gemfile			app			config.ru		lib			postcss.config.js	tmp
.DS_Store		.gitignore		Gemfile.lock		babel.config.js		db			log			public			vendor
.browserslistrc		.ruby-version		README.md		bin			docker-compose.yml	node_modules		storage			yarn.lock

アプリケーションのビルド

rails newによりgemfileが書き変わるので、書き換わったファイルでイメージをビルドしなおします。

ビルドを実行すると、Dockerfileがもう一度実行されるので、bundle installも実行されます。

$ docker-compose build

Successfully built 33a02920b593、Successfully tagged rails-vue_web:latestのように表示されればビルド成功です。

データベース設定ファイルの編集

DBに接続するための情報をconfig/database.ymlに追記します。

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

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: myapp_production
  username: myapp
  password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>


追記するのは、3行のみです。

データベースを作成

Dockerコンテナ内に作成したRailsアプリケーションの中でDBを生成します。

$ docker-compose run web rails db:create


「アプリケーション名_development」と「アプリケーション名_test」の2つのBが生成されます。

$ docker-compose run web rails db:create
Starting rails-vue_db_1 ... done
Creating rails-vue_web_run ... done
Created database 'rails_vue_development'
Created database 'rails_vue_test'


コンテナを起動

Dockerコンテナ内のrailsの下準備が終わったので、コンテナを起動します。

$ docker-compose up


きちんと起動できるか確かめるために、-dオプションは付けない方が推奨です。

-dをつけた場合はバックグラウンドでの起動となるため、エラーやアクセスログが表示されません。

http://0.0.0.0:3000 にアクセスして、Railsのページが表示されれば成功です。

ページを表示する

http://0.0.0.0:3000/home/index で別のページが表示されるようにします。

homeコントローラーのindexアクションを作成します。

rails g <コントローラ名> <アクション名>

実例

コンテナの外から、コマンドを実行します。

$ docker-compose run web rails g controller home index
Creating rails-vue_web_run ... done
Running via Spring preloader in process 22
      create  app/controllers/home_controller.rb
       route  get 'home/index'
      invoke  erb
      create    app/views/home
      create    app/views/home/index.html.erb
      invoke  test_unit
      create    test/controllers/home_controller_test.rb
      invoke  helper
      create    app/helpers/home_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/home.scss

コントローラ、ビューファイル、SCSS、ルーティングなど、ページ表示に必要なファイル群が一気に生成されます。

http://0.0.0.0:3000/home/index にアクセスして以下のページが表示されればOKです。

Dockerコンテナの停止

Dockerコンテナを停止する場合は、ターミナル(黒画面)で ctrl + cをクリックします。

Gracefully stopping... (press Ctrl+C again to force)
Stopping rails-vue-web    ... done
Stopping rails-vue-db     ... done

バックグラウンドで起動している場合

docker-compose up -d dオプションをつけてバックグラウンドで起動している場合は、docker stop コンテナ名 で停止します。

コンテナ名の確認には、docker psを使います。(起動中のコンテナ一覧を表示するコマンド)

$ docker ps
CONTAINER ID   IMAGE                       COMMAND                  CREATED         STATUS         PORTS                                            NAMES
53b3be4d01e2   rails-vue_web               "entrypoint.sh bash …"   7 seconds ago   Up 4 seconds   0.0.0.0:3000->3000/tcp                           rails-vue-web
30c07ab7c0aa   postgres                    "docker-entrypoint.s…"   7 seconds ago   Up 6 seconds   5432/tcp                                         rails-vue-db


停止したいコンテナが複数ある場合は、docker stop の後にスペースを開けてつなげて指定できます。

$ docker stop rails-vue-web rails-vue-db
rails-vue-db
rails-vue-web

コンテナの再起動

コンテナを再起動する場合は、docker-compose.ymlがあるディレクトリに移動して、以下を実行します。

docker-compose up
docker-compose up -d

コンテナの中に入る

コンテナ内のRailsアプリケーションやDBサーバーにアクセスするには、コンテナが起動中の状態で以下を実行します。

docker exec -it コンテナ名 bash


例:Railsコンテナに入る

$ docker exec -it rails-vue-web bash
root@8886c5cb663c:/rails-vue#

Railsの対話モードに入るにはこの状態で rails c を実行します。

root@8886c5cb663c:/rails-vue# rails c
Running via Spring preloader in process 44
Loading development environment (Rails 6.1.4)
irb(main):001:0>

コンテナから抜ける

Railsの対話モードおよび、コンテナから抜ける時はどちらもexitです。

#Railsの対話モードから抜ける
irb(main):001:0> exit

#Dockerコンテナから抜ける
root@8886c5cb663c:/rails-vue# exit
exit
$


DBサーバーコンテナに入る

$ docker exec -it rails-vue-db bash
root@be55a9db18e3:/#


PostgreSQLの対話モードに入る。

root@be55a9db18e3:/# psql -H -U postgres
psql (13.0 (Debian 13.0-1.pgdg100+1))
Type "help" for help.

postgres=#

コンテナから抜ける

DBサーバーの対話モードおよび、コンテナから抜ける時はどちらもexitです。

#Postgresの対話モードから抜ける
postgres=# exit

#Dockerコンテナから抜ける
root@be55a9db18e3:/# exit
exit
$
タイトルとURLをコピーしました