Rails
環境構築
docker
docker-compose

DockerでRuby on Railsの開発をしよう

追記(2018/7/10)
・Dockerfileからmysql-clientを削除
 なくても大丈夫だった
・docker-compose.ymlに追記
 dbのパスワードを空白にするパターンを書いた
・よく使うコマンドのDocker Compose
 bundle installがうまくいかないかもしれない
 Gemfileを変更するたびにbuildをすれば解決

追記(2018/7/16)
・Dockerの導入に記事のリンクを追加

はじめに

先日、新たにMacBookProを購入したので、環境構築を最初から行うことになりました。
そこで、流行っているDockerを触ろうと決意。
Qiitaの記事をいくつか漁りながら進めていましたが、複数の記事を行き来するのが面倒になったので、自分&布教用にまとめました。(補足のリンクが多いだろ!というツッコミはなしで)
堅苦しい文が続きますが、初めての方はぜひ最後まで読んで一緒にDockerを使いましょう。

Dockerとは

Dockerは、Docker社が開発している、コンテナ型の仮想環境を作成、配布、実行することができるプラットホームのこと。
公式サイト:https://www.docker.com/

その利点は、効率の良さです。この効率の良さというのは、コンテナ型の仮想化という技術によって実現されています。
従来、開発を行う場合は、ハイパーバイザー型による仮想化が主でした。しかし、ハイパーバイザーと呼ばれるプログラムが介入することで、性能低下やリソースを環境ごとに用意する必要があるといったデメリットがありました。

ここで登場するのがコンテナ型の仮想化です。
Dockerでは、コンテナという単位で仮想化を行うため、先ほど挙げたハイパーバイザー型のようなデメリットがありません
また、Dockerを用いて環境を構築することで、誰でもどこでも同じ環境で開発を行うことができます。

下の図を見るとイメージしやすいです。

655101.png
(Docker公式サイトより引用)

少し情報が古いですが、ドットインストールにレッスンがあったので、基本操作はそちらで手軽に学習できます。
Docker入門(全11回)-ドットインストール

Docker Composeとは

Docker Composeは、複数のコンテナをまとめて管理(オーケストレーション)してくれるツールです。
専用のファイル(docker-compose.yml)を書いて、コマンドを打つだけで使える非常に便利なものです。
最初はやや難しく感じるかもしれませんが、Ruby on Railsの開発では、最低2つのコンテナを使うため、Dockerを扱う上で必須なものになっています。

開発環境の構築

今回扱うもの

  • ruby 2.3.1
  • rails 5.1.4
  • mysql 5.7
  • Docker for Mac CE(他のOSでもだいたい同じ?)

Dockerの導入

こちらのDocker公式サイトからダウンロードできます。
mac版、Windows版、Linux版から選んでください。
Windows版は、Proのみとなっているので、tool-boxを使う。
→先日参考記事を書きました。Windows10HomeだけどDockerで開発してもいいよね!!

他のバージョンの方は、公式サイトのInstall Docker Composeを参考にしてください。

必要なファイルの作成

今回は、Docker Composeでコンテナの管理を行うことにします。
最初から始める場合は、以下の4つのファイルを作成するところから始まります。

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

それでは順番に作成しましょう。

Dockerfile

Dockerfile
FROM ruby:2.3.1
ENV LANG C.UTF-8

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

RUN gem install bundler

WORKDIR /tmp
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
RUN bundle install

ENV APP_HOME /myapp
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
ADD . $APP_HOME

コマンドと意味がわかれば、すぐに読めるようになるでしょう。
今回使用したコマンドについて、簡単に説明します。

コマンド              意味
FROM ベースとなるDockerイメージを指定
ENV 環境変数を設定
RUN shellの実行を行う
WORKDIR 起点となるディレクトリを設定 相対パスを使うときに起点になる
ADD ファイル、ディレクトリなどをコンテナの指定されたパスにコピー

"WORKDIR /tmp"でbudle installが早くなるらしいです。

この他にも多くのコマンドが存在するので、気になる方は「Dockerfileについて」で確認してください。
作り方については、以下の記事が参考になります。
効率的に安全な Dockerfile を作るには
Dockerfile のベストプラクティス
Dockerfileを書くときに気をつけていること10選

docker-compose.yml

docker-compose.yml
version: '3'

services:
  web:
    build: .
    ports:
      - "3000:3000"
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
      - bundle:/usr/local/bundle
    depends_on:
      - db
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
            # MYSQL_ALLOW_EMPTY_PASSWORD: "yes"  パスワードなしにしたい場合はこれ
    ports:
      - '3306:3306'
    volumes:
      - mysql_data:/var/lib/mysql
volumes:
  bundle:
  mysql_data:

いろんな記事を探すと、version2で記述しているものもありますが、今回は最新のversion3です。
services内に、docker-composeで扱うコンテナについての記述を行います。
書かれている内容について、簡単に説明します。

web

コマンド                    意味
build コンテナを構築するDockerfileがあるディレクトリを指定
ports ポートの番号を指定
command コンテナをビルドしたときに実行するコマンド
volumes ホスト上のプロジェクト用のディレクトリを、コンテナ内の /myapp にマウントし、イメージを再構築しなくてもコードの変更が行えるようにする
depens_on リンクするサービス(ここではdb)

db

コマンド               意味
image データベースとして必要なイメージを指定 ない場合はpullしてくる
environment 環境変数を追加(ここではMySQLのパスワードを設定)
ports webとほぼ同様
volumes webとほぼ同様 

詳しくは「Docker Compose - docker-compose.yml リファレンス」を参照してください。

Gemfile

Gemfile
source 'https://rubygems.org'

gem 'rails', '5.1.4'

今はこれだけで大丈夫です。

Gemfile.lock

terminal
$ touch Gemfile.lock

Gemfile.lockは中に何も記述しなくて大丈夫です。
これで準備は整いました。

Railsプロジェクトの作成と起動

Railsプロジェクトの作成の作成を行います。
ターミナルで以下のコマンドを打ちます。

terminal
$ docker-compose run web bundle exec rails new . --force --database=mysql --skip-bundle

データベースをオプションでmysqlに指定。
次に、config/database.ymlのdefault部分を変更します。

config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password    # docker-compose.ymlのMYSQL_ROOT_PASSWORDで指定したもの
  host: db                           # docker-compose.ymlのサービス名

準備が済んだので、コンテナを操作していきます。
GitでDocker関係のファイルを管理している場合は、cloneした後にこの下から始めることになります。

terminal
# コンテナをビルド
$ docker-compose build

# コンテナの作成&起動(バックグラウンド)
$ docker-compose up -d

起動したコンテナを"control+c"で停止するとエラーが出るようなので、バックグラウンドで起動し続けておくか、ターミナルのタブを増やすことをお勧めします。
停止するときは"docker-compose stop"もしくは"docker-compose down"(コンテナが削除される)

Webブラウザを開いて、アドレス欄に"localhost:3000"と入力する。
c61fce54-fb72-46df-b01c-14f333424316.jpg
画像のような画面が表示されれば成功です。

よく使うコマンド

Docker

# 今あるイメージを確認
docker images

# イメージの削除
docker rmi image_id

# コンテナの確認(-aなしだと起動中のコンテナのみ)
docker ps -a

# コンテナの削除
docker rm container_id

その他のコマンドは「リファレンス」や「Dockerコマンドメモ」を参照してください。

Docker Compose

# コンテナをビルド
docker-compose build

# コンテナの起動
docker-compose start

# コンテナの作成&起動
docker-compose up

# コンテナの停止
docker-compose stop

# コンテナの停止&削除
docker-compose down

# bundle installを実行 うまくいかないかも?
docker-compose exec web bundle install

# db関係(例)
docker-compose exec web rails db:create

# railsコマンド(例)
docker-compose exec web rails g controller controller_name

コンテナの起動や停止について諸説ありますが、私は"up-down"ではなく"start-stop"を使います。
上記のコマンドに含まれているwebは、docker-compose.ymlで指定したサービス名のことです。
詳しい解説やその他のコマンドは「docker-compose コマンドまとめ」や「docker-composeコマンド」を参照してください。

おわりに

拙い文章ですが、ここまで読んでいただきありがとうございます。
もし不適切な内容があれば、コメント欄で優しく教えていただけると助かります。
修正や補足をします。

今後は、Kubernetesの勉強もしたいので、きっかけがあれば記事にするかもしれません。

参考

Dockerによるアプリケーション開発環境構築ガイド(Amazonへのリンク)
Docker入門 #5 【Ruby on Rails5環境構築】
[Rails] DockerでRails + MySQLの開発環境をつくる手順
[Rails+MySQLなAPIサーバの開発環境をDocker Composeで作る