BLOG

Docker+MySQL+Railsの開発環境を作る

こんにちは!りゅうです。
今回も前回に引き続き、Dockerの記事を書いてみました。内容はタイトルの通りDocker+MySQL+Railsの開発環境を作るのですが、焦点はdocker-compose.ymlを使うことです。
Railsのことも触れましたが、自分は初めてだったので不足しているところは色々調べながら書いていきました。

この記事で実現したいこと
docker-compose.ymlの基本的な扱い方、書き方、内容が理解できるようになること
Railsの初歩的な部分を理解できるようになること

前回と同様Dockerが使える環境を前提として書いています。

こちら(Udemy講座)を参考にしました。解説が丁寧でとても分かりやすい講座でした。
米国AI開発者がゼロから教えるDocker講座

docker-compose.ymlとは

今回使っていくdocker-compose.ymlはDockerfileと比較すると…
・複数のコンテナを一つにまとめることができる
・コンテナの中身というよりは、コンテナをどのように使っていくかなどを定義する
・コンテナの立ち上げが楽になる
こんな感じだと思います。
docker-compose.ymlはDockerfileも合わせて使っていたりします。

必要なファイルを用意する

早速、開発環境の作成に必要なファイルを4つ用意していきます。

Dockerfile
Railsのコンテナにどんなものを用意するか記載しています。

Gemfile
Railsで使用するgem(Rubyのライブラリ)が一覧で書かれたファイルです。これに従ってgemがインストールされます。
ここでは使用するRailsのみ記載し、あとは実行する中で色々勝手に追記されています。

Gemfile.lock
Gemfileでインストールしたgemのバージョン情報などが書かれています。ファイルだけ用意し、特に中身の編集はしません。

docker-compose.yml
今回の主役です。ここにはRailsのコンテナとMySQLのコンテナを立ち上げる時の情報を記載しています。

ファイルを作成した後の環境構築フォルダ直下はこんな感じです。

まずはDockerfileから記述していきます。
Dockerfileについては前回の記事で基本的な書き方について書いてみたので、良かったら合わせて読んでみてください。

FROM ruby:2.5
RUN apt-get update && apt-get install -y \
    build-essential \
    libpq-dev \
    nodejs \
    default-mysql-client \
    yarn

WORKDIR /RailsMySQLSample
COPY Gemfile Gemfile.lock /RailsMySQLSample/
RUN bundle install

Dockerfileをビルドした時の流れとしては、rubyのベースイメージを取得、そのあと必要な開発ツールをインストールしています。
WORKDIR以降でコンテナを立ち上げる前にGemfile、Gemfile.lockをコピーし、bundle installで不足したgemがあればインストールをしています。

続いてGemfileとGemfile.lock

source 'https://rubygems.org'
gem 'rails', '~>5.2'

railsの5.2以上のバージョンを https://rubygems.org から取得するよう定義します。

Gemfile.lockは空ファイルでOKです。

最後にdocker-compose.yml

version: '3'

services:
    web:
        build: .
        ports:
            - '3000:3000'
        volumes:
            - '.:/RailsMySQLSample'
        tty: true
        stdin_open: true

Railsコンテナ部分のみで、DB情報はあとで追加していきます。
記述の仕方はJson形式で書かれています。.ymlがJsonの上位互換みたいな感じでJsonでできることはほぼできるようです。あとはインデントの深さで意味付けされています。

要素名要素の説明指定内容の説明
version docker-composeのバージョンを指定 バージョンの数字
services この後にコンテナ情報をインデント一つ下げて定義
web コンテナの名前、任意でOK webアプリのコンテナは大体webと定義
buildビルド時のDockerfileがあるパスを指定カレントディレクトリをビルド時のパスとして指定
portsホストとコンテナのポート番号を指定
ホスト:コンテナ
ホストもコンテナも3000を指定
(Railsのデフォルトポートが3000みたいです)
volumes コンテナの参照先を指定
ホスト:コンテナ
ホスト側のカレントディレクトをコンテナのRailsMySQLSampleで参照
tty 出力表示をきれいにするか
-tオプションと同様
true/falseを指定
trueなのでする
stdin_open 入力操作できるようにするか
-iオプションと同様
true/falseを指定
trueなのでする

docker-composeコマンドを使ってみる

必要なファイルを準備できたら、docker-composeのコマンドを使ってビルドしてみます。

ターミナルを開き、以下のコマンドでビルド、コンテナ起動ができます。

docker-compose up -d --build
コマンド/オプション名説明
upコンテナを起動
対象のイメージがない場合は自動でビルド
-dバックグラウンドでコンテナ起動
指定しない場合、コンテナ起動中、起動に使ったターミナルは操作できない
–buildコンテナを起動する前に強制的に再ビルドし直してくれる
ソースを修正したときなどに指定する

以下のコマンドでビルドとコンテナ起動を別々にできます。

docker-compose build
docker-compose up -d

ビルド、起動したらコンテナが立ち上がっているか確認してみます。

docker ps

起動が確認できたら、以下のコマンドでコンテナの中に入って操作をしてみます。

docker-compose exec web bash

docker-compose exec
docker-compose exec コンテナ名 実行コマンド
でコマンドの実行ができます。 コンテナ名(web)はdocker-compose.ymlの「services:」の後に定義したやつです。

docker-compose.yml で「tty:」と「stdin_open:」 が未定義の場合、以下のコマンドで全く同じ動作をしてくれます。
docker-compose exec -it コンテナ名 実行コマンド
それなので定義しておいた方が楽そうですね。

コンテナに入れたら、Gemfileに書いたRailsがちゃんと入っているか確認してみます。

rails -v

Gemfileに指定した5.2以上のバージョンで入っていました。

Railsが確認できたら以下のコマンドでRailsアプリ開発に必要なものを入れてみます。

rails new . --force -d mysql --skip-bundle 
コマンド/オプション名説明
newRailsアプリに必要なものを指定したディレクトリにインストール
カレントディレクトリを指定
-d使用するデータベースの指定
MySQLを使うのでmysqlと指定
–skip-bundlebundle installを行わない(gemのインストール)
Dockerfile内でコンテナビルド時にbundle installを指定するので、ここでは行わない

コマンドを実行すると色々と作り始めました。

今回「rails new . 」で指定したコンテナのカレントディレクトリRailsMySQLSample、これはホストのDockercompose.ymlなどがあるディレクトリをマウント(参照)しているので、ホスト側に色々と作られていました。

ここまででDBなしのRails開発環境ができました。
続いてDBコンテナを作成していくので、一旦exitでコンテナからは抜けます。

先ほど色々作られた中からconfig>database.ymlを探して修正していきます。

10行目を過ぎたあたりに以下のような記述が見つかると思います。

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  host: localhost

この記述を少し修正していきます(下3つ修正)。

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:<%= ENV.fetch("DATABASE_PASSWORD") %>
  host: db
  port: 3306

password: には環境変数 DATABASE_PASSWORD からパスワードを取得してくるように指定しています。環境変数へのパスワードはこの後修正するdocker-compose.ymlで定義していきます。
host: localhostにはこれから作成するDBコンテナの名前「db」を指定しています。
port: を追記し、MySQLのデフォルトポート3306を指定しています。


最初に作ったdocker-compose.ymlにDBコンテナを作成することと、webコンテナがDBコンテナへ接続できるように修正していきます。

version: '3'
volumes: 
    data:
services:
    web:
        build: .
        ports:
            - '3000:3000'
        volumes:
            - '.:/RailsMySQLSample'
        tty: true
        stdin_open: true
        environment:
            - 'DATABASE_PASSWORD=password' 
        depends_on: 
            - db
        links:
            - db
    db:
        image: mysql:5.7
        ports:
            - '3306:3306'
        volumes:
            - 'data:/var/lib/mysql'
        environment:
            MYSQL_ROOT_PASSWORD: password

 

追記した箇所
2,3行目(DBコンテナのマウント先、24行目でマウントの定義)

volumes: 
    data:

volumes: はdocker内に定義された領域のようです。そのためマウント先のdataフォルダはホスト側にあるわけではないそうです。

13~18行目(webコンテナとDBコンテナの接続)

        environment:
            - 'DATABASE_PASSWORD=password' 
        depends_on: 
            - db
        links:
            - db

environment:にDB接続時のパスワードを指定しています。database.ymlに使われるやつです。
depends_on:はdbコンテナが起動してからwebコンテナを起動するという指定です。
links:でwebコンテナとdbコンテナを繋げています。

19~26行目(DBコンテナ部分)

    db:
        image: mysql:5.7
        ports:
            - '3306:3306'
        volumes:
            - 'data:/var/lib/mysql'
        environment:
            MYSQL_ROOT_PASSWORD: password

DBコンテナの基本情報になるポート、マウント先、rootユーザのパスワードを指定しています。

ここまででホスト側で用意するものは一通り完成しました!あとはコマンド入力をしながら作業を進めていきます。

今あるコンテナはRailsのみのコンテナなので、一旦コンテナは以下のコマンドで削除します。

docker-compose down

古いコンテナが残ったままビルド、起動し直すと古いデータの一部が残っていたりするので、意図した通り動かすためにはコンテナを削除して作り直すのがいいんだと思います。

コンテナを削除したらwebコンテナを起動したときに使ったコマンド

docker-compose up -d --build

でビルド、起動し直しです。

再びコンテナに入っていきます。

docker-compose exec web bash

以下のrailsコマンドでDBを作ります。

rails db:create

database.ymlの20行目を過ぎたあたりにDB名を定義しているところがあります。DB名を変更したい場合はここで変えられます。

簡易アプリの作成をしていきます。
rails g scaffold というrailsのコマンドを使用してみます。
引数には「見出し 項目名1:型 項目名2:型…」のような感じで指定です。

rails g scaffold Member Name:string Sex:string

上記の指定で以下のような画面の入力項目やコントローラ・モデルも自動で用意してくれます。

次にDBへテーブルやカラムの反映を行うため、以下のコマンドでマイグレーションを実行してみます。

rails db:migrate

実行後DBコンテナに反映されていました。

最後に以下のコマンドでサーバを起動し、localhost:3000にアクセスしてみます。

rails s -b 0.0.0.0

-b 0.0.0.0はwebコンテナが持っている全てのネットワークインターフェースと結び付けをしてくれるので、コンテナ外部からでもコンテナのlocalhostにアクセスができるようになるようです。(ネットワーク苦手なので学習が必要…)

問題なくアクセスできると、Railsのデフォルト画面が表示できると思います。

rails g scaffold コマンドの見出し名(ここではMember)を複数形にした/membersをポート3000の後に指定すると以下の画面が表示できると思います。

最後に

学習したことを一通り書いてみましたが、思いのほか長くなってしまいました…。
今回は記載する内容が多かった分、理解が曖昧で記事にアウトプットするには何度も見直しや深堀が必要でした。ですがその甲斐あってDockerの基礎はより自分のものにできたと感じています。

改めて今回大変お世話になったこちらのUdemy講座、Dockerの理解を深めるのに非常におすすめだと個人的には感じているので、是非ご視聴してみてください。
米国AI開発者がゼロから教えるDocker講座

今回は以上になります。
最後までご覧いただき、ありがとうございました。

BLOGトップへ戻る