Docker上にRailsを構築するために必要なファイル
Dcoker上にRailsを構築で必要なファイルは次の5つです。
- Dockerfile
- Gemfile
- Gemfile.lock
- entrypoint.sh
- docker-compsoe.yml
$ mkdir rails-vue
$ cd rails-vue
Dockerfileの作成
Rubyのバージョンに指定がない場合は、Ruby公式サイトで安定版を調べた後、docker hubのRubyイメージで該当するものを確認します。
Rails6からはJavaScriptや画像などのアセットを管理するためにWebpackerを使います。Webpackerをインストールするために、Node.jsとYarnをインストールしておく必要があります。
DBはPostgreSQLを指定しています。
$ 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でも何でもいいです。
ENV DEBCONF_NOWARNINGS=yes
apt-utilsがないために表示されるエラー対策として、環境変数でENV DEBIAN_FRONTENDを設定しています。
apt-utilsはなくても問題なく動くため、軽量化のためにもインストールしません。
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を指定
最初に作成した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
$